卡牌游戏II
来源:互联网 发布:仙界网络直播间80txt 编辑:程序博客网 时间:2024/05/13 21:26
题目链接:http://acm.tongji.edu.cn/problem.php?id=1093
题目描述
有N张卡片,上面印着整数a1,a2,a3……an,
可以选取其中任意数量张卡片,求出一个和S,共有2^N-1个和
要求出最小的前N个和分别是多少
输入格式
题目包含多组数据。
输入的每一行有一个整数T(1<=T<=5)代表有T组数据
对于每组数据分为两行:
第一行有两个整数N,K(其中1<=N<=200000,1<=K<=min(2^N-1,200000))
第二行有N个整数,分别是a1,a2,a3……an(-10^8<=ai<=10^8)
输出格式
对于每组数据,输出的第一行为Case #x:,其中x是数据编号(从1开始) 第二行到第K行,每行一个整数,从小到大。
第二行输出一个非负整数,为正常需要输出的K的数字的和 Mod 99989的结果。
样例
样例输入:
2
2 1
1 1
3 3
-1 0 1
样例输出:
Case #1:
1
Case #2:
99987
题解:
因为要求的是最小的值,所以最小值一定是取所有的负数,且不取任何整数的情况。
又因为少取一个负数就相当于多拿一个绝对值相等的正数,因此就可以把负数的和记录下来,并将负数转化为正数进行处理。
下一步就是从N个正数当中取数,使得和从小到大排列的问题了,这里可以使用优先队列的bfs进行处理。
记得负数转化完之后,全取和全不取的情况会发生变化,要单独考虑。
这里的bfs用的是优化过的方式。正常的bfs是处理完第i张的情况后,将第i+1~n张卡分别加入并推入队列,时间复杂度为O(N^2*logN/2),太高了。
因此这里使用标记next,每次bfs的时候除了加入新卡外,额外进行一次“回溯”操作,将不取第next张卡而取第next+1张卡的情况加入队列。因为卡片是从小到大排列的,因此这种操作既保证了小数更早处理,也大大减少了bfs的操作数(在k远小于N^2的情况下)。
最终时间复杂度为O(klogN)。
程序:
#include<iostream>#include<string>#include<cstdio>#include<set>#include<map>#include<stack>#include<list>#include<vector>#include<queue>#include<algorithm>#include<cstring>#include<cmath>#include<fstream>using namespace std;typedef long long ll;const int M = 99989;ll n,k,sum,min_,ans;vector<ll> card;void bfs(){ priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>> > QW;//存放当前的和Val以及下一张可以取的卡编号next QW.push(make_pair(0,0)); sum = 0; bool sp = true; while(sum < k && !QW.empty()){ ll val = QW.top().first,next = QW.top().second;QW.pop(); if (next < card.size() && !(val == 0 && next == 0))//如果还有能取的卡 QW.push(make_pair(val-card[next-1]+card[next], next+1));//将不取当前卡片,而是取下一张的情况推入队列 if (val == -min_ && sp){//全不取的特殊情况 sp = false; sum--; } ans = (ans + min_ + val) % M; sum++; if (next < card.size()) QW.push(make_pair(val+card[next], next+1));//取下一张卡 }}void init(){ cin >> n >> k; int t; min_ = 0; ans = 0; card.clear(); for(int i = 0;i < n;++i){ cin >> t; { if (t < 0){ min_ += t;//保存负数的和 t = -t; } card.push_back(t); } } sort(card.begin(),card.end());}int main(){ int t; cin >> t; for (int k = 1;k <= t;++k){ init(); printf("Case #%d: \n",k); bfs(); if (ans < 0) ans += M; cout << ans << endl; }}
- 卡牌游戏II
- 跳跃游戏 II
- LintCode:跳跃游戏 II
- [Lintcode]跳跃游戏 II
- 跳跃游戏II
- 跳跃游戏 II-LintCode
- lintcode --跳跃游戏II
- [LintCode] 跳跃游戏II Jump Game II
- Coding4Fun:开始游戏开发 II
- 【9018p1440】数字游戏II
- lintcode-跳跃游戏II-117
- [hihoCoder]#1615 : 矩阵游戏II
- LeetCode Jump Game II 前跳游戏II
- LeetCode | Jump Game II(跳跃游戏II)
- LeetCode 294. Flip Game II(反转游戏II)
- 117.Jump Game II-跳跃游戏 II(中等题)
- 45. Jump Game II(跳跃游戏II)
- 推箱子II游戏代码的改进
- TODAY ISSUE
- Fiddler抓取https的原理
- matlab2016a自带的disparity函数
- 黄聪:异步加载JS的4种方式(详解)
- Java学习之权限修饰符与常见内容修饰
- 卡牌游戏II
- QT图形界面在工业数据采集显示系统的应用
- python os.path模块学习
- 由App的启动说起
- VirtualBox挂载Linux之后,启动报错:Error relaunching VirtualBox VM process: 5 .
- 状态模式(State Pattern)
- angular 里$$hashkey问题?
- 谈谈iOS中Categories(分类)、Extensions(类扩展)和继承的区别
- Java中有5种创建对象的方式