UVa Live 7147 贪心(2014 上海区域赛)
2015-09-10 13:06
316 查看
题目链接
这个题已经过了一年了。。。本来当时就想写题解但是没找到题。。最近有人问我才知道原来UVa Live有历年题目。。。
去年在现场的时候这题也是卡了好久。。。重写了两三次。。封榜了才过。。
题意:有n只队伍,每只队伍要和其他n-1只队伍比赛,每场比赛获胜得a分,平局得b分,败北得c分,共有m只队伍可以晋级,问最高淘汰分和最低晋级分分别是多少。
思路:这个题的细节真的很多。。
首先如果获胜分<败北分,互换两个分数。
然后考虑分数尽量平均的分配方式:
在偶数个人中,想让所有人分数相等有两种方式,所有人平局或赢一半的人输一半的人;
在奇数个人中,要么所有人平局,要么一部分人多输一局。
最高淘汰分:第m+1人,对于其后面的n-m-1人都应该选择赢或者平局,对于前面的m人,按照上面的分数分配方式选择分较高的一种。
最低晋级分:第m人,对于其前面的m-1人都应该选择输或平局,对于后面的n-m人,按照上面的分数分配方式选择分较少的一种。
这道题的细节很多,有一个需要注意的地方是对于奇数个人m,不应该比较m/2 * (win + lose)和 m * draw,这样draw会多算一个,我就在这个地方卡了很久。。。(好像当时比赛的时候也在这里卡了很久。。)
#include <iostream>
#include <algorithm>
using namespace std;
main() {
long long n, m, win, draw, lose;
int t, cas = 1;
cin >> t;
while(t--){
cin >> n >> m >> win >> draw >> lose;
if(win < lose) swap(win, lose);
long long pass = 0, out = 0;
if(m % 2 == 0){
if(draw < lose) pass = draw * (n - 1);//如果平局分数最低 那么最低晋级分就是所有人平局
else {
pass = (m - 1) * lose;//和前面的m-1人比一定是输的
long long p = n - m;
pass += (p / 2) > 0 ? min(win + lose, draw + draw) * (p / 2) : 0;//和后面的人比,看哪种分数相同的情况分数最低
if(p % 2) pass += min(draw, win);//如果是奇数情况,那么要么赢最后一名,要么所有人平局,反正总分要低
}
if(draw > win) out = draw * (n - 1);//如果平局分数最低 那么最高淘汰分就是所有人平局
else{
out = (m / 2) > 0? max(win + lose, draw + draw) * (m / 2) : 0;//和前面的人比,看哪种分数分数相同的情况分数最高
out += (n - m - 1) * win;//和后面的人比一定是赢的
}
}
else {
if(draw < lose) pass = draw * (n - 1);
else{
pass = (m - 1) * lose;
long long p = n - m;
pass += (p / 2) > 0 ? min(win + lose, draw + draw) * (p / 2) : 0;
if(p % 2) pass += min(win, draw);
}
if(draw > win) out = draw * (n - 1);
else {
out = (m / 2) > 0? max(win + lose, draw + draw) * (m / 2) : 0;
out += max(draw, lose) + (n - m - 1) * win;//和前面的人比 如果是奇数情况 要么平要么输 选分高的一种
}
}
cout << "Case #" << cas++ << ": " << out << " " << pass << endl;
}
}
这个题已经过了一年了。。。本来当时就想写题解但是没找到题。。最近有人问我才知道原来UVa Live有历年题目。。。
去年在现场的时候这题也是卡了好久。。。重写了两三次。。封榜了才过。。
题意:有n只队伍,每只队伍要和其他n-1只队伍比赛,每场比赛获胜得a分,平局得b分,败北得c分,共有m只队伍可以晋级,问最高淘汰分和最低晋级分分别是多少。
思路:这个题的细节真的很多。。
首先如果获胜分<败北分,互换两个分数。
然后考虑分数尽量平均的分配方式:
在偶数个人中,想让所有人分数相等有两种方式,所有人平局或赢一半的人输一半的人;
在奇数个人中,要么所有人平局,要么一部分人多输一局。
最高淘汰分:第m+1人,对于其后面的n-m-1人都应该选择赢或者平局,对于前面的m人,按照上面的分数分配方式选择分较高的一种。
最低晋级分:第m人,对于其前面的m-1人都应该选择输或平局,对于后面的n-m人,按照上面的分数分配方式选择分较少的一种。
这道题的细节很多,有一个需要注意的地方是对于奇数个人m,不应该比较m/2 * (win + lose)和 m * draw,这样draw会多算一个,我就在这个地方卡了很久。。。(好像当时比赛的时候也在这里卡了很久。。)
#include <iostream>
#include <algorithm>
using namespace std;
main() {
long long n, m, win, draw, lose;
int t, cas = 1;
cin >> t;
while(t--){
cin >> n >> m >> win >> draw >> lose;
if(win < lose) swap(win, lose);
long long pass = 0, out = 0;
if(m % 2 == 0){
if(draw < lose) pass = draw * (n - 1);//如果平局分数最低 那么最低晋级分就是所有人平局
else {
pass = (m - 1) * lose;//和前面的m-1人比一定是输的
long long p = n - m;
pass += (p / 2) > 0 ? min(win + lose, draw + draw) * (p / 2) : 0;//和后面的人比,看哪种分数相同的情况分数最低
if(p % 2) pass += min(draw, win);//如果是奇数情况,那么要么赢最后一名,要么所有人平局,反正总分要低
}
if(draw > win) out = draw * (n - 1);//如果平局分数最低 那么最高淘汰分就是所有人平局
else{
out = (m / 2) > 0? max(win + lose, draw + draw) * (m / 2) : 0;//和前面的人比,看哪种分数分数相同的情况分数最高
out += (n - m - 1) * win;//和后面的人比一定是赢的
}
}
else {
if(draw < lose) pass = draw * (n - 1);
else{
pass = (m - 1) * lose;
long long p = n - m;
pass += (p / 2) > 0 ? min(win + lose, draw + draw) * (p / 2) : 0;
if(p % 2) pass += min(win, draw);
}
if(draw > win) out = draw * (n - 1);
else {
out = (m / 2) > 0? max(win + lose, draw + draw) * (m / 2) : 0;
out += max(draw, lose) + (n - m - 1) * win;//和前面的人比 如果是奇数情况 要么平要么输 选分高的一种
}
}
cout << "Case #" << cas++ << ": " << out << " " << pass << endl;
}
}
相关文章推荐
- svn系列之八基本操作——清除登录信息、查看操作日志
- linux杀死进程报错问题
- quartz2.2.1与spring3.2.8版本不兼容的问题
- 全局 常量定义和字符串的一些比较
- 戴姆勒股份公司
- Maven3路程(三)用Maven创建第一个web项目(1)
- 软件的可维护性问题知识与分析(转)
- Android app运行时找不到activity的情况之一:应用程序包名不统一
- First Bad Version
- java Tomcat数据库连接池
- UltraISO制作U盘启动盘安装Vmware ESXI 5.5 中途卡住解决方法
- word2007 去掉句首字母大写
- docker 打造node js 运行环境
- DOM3 textInput事件
- java bean 转为JSON
- 台湾国立大学机器学习技法.听课笔记(第三讲) :Kernel Support Vector Machine
- hdu1848 Fibonacci again and again(SG游戏功能)
- hdu 5030 Rabbit's String(后缀数组&二分法)
- SQL SERVER镜像配置(包含见证服务器)
- 模态窗口,在IE下是模态,在FF下不是模态,作了最大的努力来实现通用