2018 CodeM初赛A轮 下棋答案(B题) (第二道题)

2024-04-19 11:38

本文主要是介绍2018 CodeM初赛A轮 下棋答案(B题) (第二道题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:

      有一个1*n的棋盘, 上面有若干个棋子,一个格子上可能有多个棋子,

      你每次操作是先选择一个棋子,然后选择一下两个操作中的一个:

           (1)若该棋子不在(1,1),让这个棋子往左走一格,即从(1,x)走到(1,x - 1);

          (2)若该棋子不在(1,n),且这个棋子曾静到达过(1,1),让这个格子往右走一格,即从(1,x)走到(1,x+1)。

     给定一开始每个各自上有几个棋子,再给定目标每个格子上上需要几个棋子,求最少需要多少次操作。

     输入:

         第一行一个正整数n表示棋盘大小。

         第二行n个非负整数a_1,a_2,。。。,a_n 表示一开始(1,i)上有几个棋子。

         第三行n个非负整数b_1,b_2,。。。,b_n 表示目标局面里的(1,i)上有几个棋子。

     输出:

        输出一个非负整数,表示最少需要几次操作。

例子:

     输入:

        5

        0  0  1  1  0

        1  0  0  0  1

     输出:

       9


题目分析:

  典型的贪心法问题,目标数组减去起始数组,得到的向量中,如果元素为负,表示拥有多余的棋子;如果元素为正,表示,需要额外棋子,根据操作的定义,我们可以想到最有的策略是:棋盘中最右边的多余的棋子,给最左边需要的额外的棋子,坐标的相减即为所需的操作次数,而遇到在多余棋子坐标右边的需要的棋子,就需要向左移到头,再向右移,所需的操作为两个点的坐标相加。

贪心总结三点:

  1、相差为0的元素,代表不移动

  2、目标需要棋子的坐标如果在含有棋子的坐标的右边,则需要移动到最左边,然后再向右移动

  3、目标需要棋子的坐标如果在含有棋子的坐标的左边,则只需要向左移动相应格子即可

而我们的贪心算法要尽可能是第三点的操作最多,则可满足题意。

  代码

  代码核心:定义两个队列,一个队列是拥有多余棋子的队列(这个队列是从右向左入队),另一个是需要棋子的队列(这个队列是从左向右入队),根据最有策略,列队入队的方向有所不同,注意队列还要保存坐标信息,当队首的棋子数为零则出队(这里的棋子数包括所需的棋子数或是多余的棋子数)。第二步就需要判断位置信息,利用位置来确定操作次数。代码如下:

//

//  main.cpp

//  codeM初赛2

//

//  Created by Mr Gao on 2018/6/9.

//  Copyright © 2018年 Mr Gao. All rights reserved.

//


#include <iostream>

#include <vector>

#include <queue>

using namespace std;

int main(int argc, const char * argv[]) {

    // insert code here...

    int n;

    cin>>n;

    if(n == 0)

        cout<<0<<endl;

    vector<long long> start(n);

    vector<long long> end(n);

    for(int i = 0; i < n; i++)

        cin>>start[i];

    for(int i = 0; i < n; i++)

        cin>>end[i];

    queue<pair<long long,int>> hasPiece;

    queue<pair<long long,int>> needPiece;

    for(int i = 0; i < n; i++){

        long long diff = end[i] - start[i];

        if(diff > 0)

            needPiece.push(pair<long long,int>(diff, i));

    }

    for(int i = n - 1; i >= 0; i--){

        long long diff = end[i] - start[i];

        if(diff < 0)

            hasPiece.push(pair<long long,int>(-diff, i));

    }

    long long ret = 0;

    while(!hasPiece.empty()){

        if(hasPiece.front().first >= needPiece.front().first && hasPiece.front().second > needPiece.front().second){

            ret += needPiece.front().first * (hasPiece.front().second - needPiece.front().second);

            hasPiece.front().first -= needPiece.front().first;

            needPiece.front().first = 0LL;

        }

        else if(hasPiece.front().first < needPiece.front().first && hasPiece.front().second > needPiece.front().second){

            ret += hasPiece.front().first * (hasPiece.front().second - needPiece.front().second);

            needPiece.front().first -= hasPiece.front().first;

            hasPiece.front().first = 0LL;

        }

        else  if(hasPiece.front().first >= needPiece.front().first && hasPiece.front().second < needPiece.front().second){

            ret += needPiece.front().first * (needPiece.front().second + hasPiece.front().second);

            hasPiece.front().first -= needPiece.front().first;

            needPiece.front().first = 0LL;

        }

        else if(hasPiece.front().first < needPiece.front().first && hasPiece.front().second < needPiece.front().second){

            ret += hasPiece.front().first * (needPiece.front().second + hasPiece.front().second);

            needPiece.front().first -= hasPiece.front().first;

            hasPiece.front().first = 0LL;

        }

        if(hasPiece.front().first == 0LL)

            hasPiece.pop();

        if(needPiece.front().first == 0LL)

            needPiece.pop();

    }

    cout<<ret<<endl;

    return 0;

}



这篇关于2018 CodeM初赛A轮 下棋答案(B题) (第二道题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917436

相关文章

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

poj 3104 二分答案

题意: n件湿度为num的衣服,每秒钟自己可以蒸发掉1个湿度。 然而如果使用了暖炉,每秒可以烧掉k个湿度,但不计算蒸发了。 现在问这么多的衣服,怎么烧事件最短。 解析: 二分答案咯。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <c

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

【附答案】C/C++ 最常见50道面试题

文章目录 面试题 1:深入探讨变量的声明与定义的区别面试题 2:编写比较“零值”的`if`语句面试题 3:深入理解`sizeof`与`strlen`的差异面试题 4:解析C与C++中`static`关键字的不同用途面试题 5:比较C语言的`malloc`与C++的`new`面试题 6:实现一个“标准”的`MIN`宏面试题 7:指针是否可以是`volatile`面试题 8:探讨`a`和`&a`

2018秋招C/C++面试题总结

博主从8月中旬开始大大小小面试了十几家公司,至今也许是告一段落吧,希望后面会有好结果,因此总结记录一些C/C++方向常见的问题。和大家一起学习! 参考了互联网的各种资源,自己尝试归类整理,谢谢~ 一、C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。 C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构

大厂算法例题解之网易2018秋招笔试真题 (未完)

1、字符串碎片 【题目描述】一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,“aaabbaaac” 是由下面碎片组成的:‘aaa’,‘bb’,‘c’。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的 平均长度是多少。 输入描述: 输入包括一个字符串 s,字符串 s 的长度 length(1 ≤ length ≤ 50),s 只含小写字母(‘a’-‘z’) 输出描述

vulhub GhostScript 沙箱绕过(CVE-2018-16509)

1.执行以下命令启动靶场环境并在浏览器访问 cd vulhub/ghostscript/CVE-2018-16509 #进入漏洞环境所在目录   docker-compose up -d #启动靶场   docker ps #查看容器信息 2.访问网页 3.下载包含payload的png文件 vulhub/ghostscript/CVE-2018-16509/poc.png at

百度之星 2015 初赛(1) 1002 找连续数

找连续数      Accepts: 401      Submissions: 1911  Time Limit: 2000/1000 MS (Java/Others)      Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是

百度之星初赛1002(二分搜索)

序列变换    Accepts: 816    Submissions: 3578  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 给定序列 A={A1,A2,...,An} , 要求改变序列A中

百度之星初赛1006(计算几何:能包含凸包的最小矩形面积)

矩形面积    Accepts: 717    Submissions: 1619  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些