HDU 4415 贪心
2015-09-17 08:13
246 查看
HDU 4415
题目链接:
题意:
给n个怪物,每个怪物有伤害值和怪物死后会留下的宝剑数。
一个人初始有m点血。若手上无剑,则用血来砍怪,否则不消耗血量,但是斩杀一只怪物需要消耗一把宝剑。
问在保证杀怪数最多的情况下,消耗最少的血量。输出结果。
思路:
贪心。
1)第一种情况:只考虑杀死没有剑的。
2)第二种情况推理知道假如杀死有剑的,容易知道只要杀死一只,其余有剑的都能杀死。这时候用杀死所有有剑的剩余的剑去斩杀血量大的无剑的怪物。注意此处对于斩杀有剑的剩余剑数需要加1,因为第一个怪物不是用剑杀死的。剩余的怪物再用贪心的思想去用血杀掉。然后WA点就出来了。
i. 当前未确定的有剑怪物的最小血量 > 当前未确定的无剑怪物的最小血量。则用血杀死无剑怪物,同时确定此只有剑怪物是用剑杀死的。
ii. 当前未确定的有剑怪物最小血量 <= 当前未确定的无剑怪物的最小血量。则用血杀死有剑怪物。此时多出一把剑,贪心的思想用该剑杀掉无剑怪物最大血量。注意此时未确定的最小血量的那只无剑怪物仍然是未确定的。
听说数据很水,但是加粗部分没写好就会WA。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
#define gmin(a,b) ((a) < (b) ? (a) : (b))
#define gmax(a,b) ((a) > (b) ? (a) : (b))
const int MAXN = 100000 + 5;
struct Dot
{
int u, val;
}a1[MAXN], a2[MAXN];
int cnt1, cnt2, n, m;
bool cmp1(Dot a, Dot b){return a.u < b.u;}
int main()
{
// freopen("1006.in", "r", stdin);
// freopen("1006 1.txt", "w", stdout);
int t;
scanf("%d", &t);
for(int cas = 1 ; cas <= t ; cas++){
scanf("%d%d", &n, &m);
int u, v;
int u1, v1, u2, v2;
u1 = v1 = u2 = v2 = 0;
cnt1 = cnt2 = 0;
for(int i = 0 ; i < n ; i++){
scanf("%d%d", &u, &v);
if(!v) a2[cnt2].u = u, a2[cnt2++].val = v;
else a1[cnt1].u = u, a1[cnt1++].val = v;
}
// printf("cnt1 = %d, cnt2 = %d\n", cnt1, cnt2);
sort(a1, a1 + cnt1, cmp1);
sort(a2, a2 + cnt2, cmp1);
for(int i = 0 ; i < cnt2 ; i++){
if(v1 + a2[i].u > m)
break;
v1 += a2[i].u;
u1++;
}
if(!cnt1 || a1[0].u > m){
printf("Case %d: %d %d\n", cas, u1, v1);
continue;
}
for(int i = 0 ; i < cnt1 ; i++){
u2 += a1[i].val;
if(u2 > n) break;
}
v2 = a1[0].u;
u2++;
int temp = u2;
// printf("temp = %d\n", temp);
while(cnt2 > 0 && temp > cnt1)
cnt2--, temp--;
int now1 = 1, now2 = 0;
// printf("cnt1 = %d, cnt2 = %d\n", cnt1, cnt2);
while(now1 < cnt1 && now2 < cnt2){
// printf("v2 = %d\n", v2);
if(v2 + gmin(a1[now1].u, a2[now2].u) > m)
break;
v2 += gmin(a1[now1].u, a2[now2].u);
u2++;
if(u2 > n)
break;
if(a1[now1].u <= a2[now2].u)
cnt2--, now1++;
else
now2++;
}
while(now2 < cnt2){
if(v2 + a2[now2].u > m)
break;
if(u2 > n)
break;
v2 += a2[now2].u;
u2++;
now2++;
}
// printf("u1 = %d, v1 = %d\n", u1, v1);
// printf("u2 = %d, v2 = %d\n", u2, v2);
u2 = gmin(u2, n);
if(u1 > u2){
printf("Case %d: %d %d\n", cas, u1, v1);
}
else if(u1 < u2){
printf("Case %d: %d %d\n", cas, u2, v2);
}
else if(u1 == u2)
printf("Case %d: %d %d\n", cas, u1, gmin(v1, v2));
}
return 0;
}
/*
1
4 5
1 0
2 0
3 0
4 0
*/
题目链接:
题意:
给n个怪物,每个怪物有伤害值和怪物死后会留下的宝剑数。
一个人初始有m点血。若手上无剑,则用血来砍怪,否则不消耗血量,但是斩杀一只怪物需要消耗一把宝剑。
问在保证杀怪数最多的情况下,消耗最少的血量。输出结果。
思路:
贪心。
1)第一种情况:只考虑杀死没有剑的。
2)第二种情况推理知道假如杀死有剑的,容易知道只要杀死一只,其余有剑的都能杀死。这时候用杀死所有有剑的剩余的剑去斩杀血量大的无剑的怪物。注意此处对于斩杀有剑的剩余剑数需要加1,因为第一个怪物不是用剑杀死的。剩余的怪物再用贪心的思想去用血杀掉。然后WA点就出来了。
i. 当前未确定的有剑怪物的最小血量 > 当前未确定的无剑怪物的最小血量。则用血杀死无剑怪物,同时确定此只有剑怪物是用剑杀死的。
ii. 当前未确定的有剑怪物最小血量 <= 当前未确定的无剑怪物的最小血量。则用血杀死有剑怪物。此时多出一把剑,贪心的思想用该剑杀掉无剑怪物最大血量。注意此时未确定的最小血量的那只无剑怪物仍然是未确定的。
听说数据很水,但是加粗部分没写好就会WA。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
#define gmin(a,b) ((a) < (b) ? (a) : (b))
#define gmax(a,b) ((a) > (b) ? (a) : (b))
const int MAXN = 100000 + 5;
struct Dot
{
int u, val;
}a1[MAXN], a2[MAXN];
int cnt1, cnt2, n, m;
bool cmp1(Dot a, Dot b){return a.u < b.u;}
int main()
{
// freopen("1006.in", "r", stdin);
// freopen("1006 1.txt", "w", stdout);
int t;
scanf("%d", &t);
for(int cas = 1 ; cas <= t ; cas++){
scanf("%d%d", &n, &m);
int u, v;
int u1, v1, u2, v2;
u1 = v1 = u2 = v2 = 0;
cnt1 = cnt2 = 0;
for(int i = 0 ; i < n ; i++){
scanf("%d%d", &u, &v);
if(!v) a2[cnt2].u = u, a2[cnt2++].val = v;
else a1[cnt1].u = u, a1[cnt1++].val = v;
}
// printf("cnt1 = %d, cnt2 = %d\n", cnt1, cnt2);
sort(a1, a1 + cnt1, cmp1);
sort(a2, a2 + cnt2, cmp1);
for(int i = 0 ; i < cnt2 ; i++){
if(v1 + a2[i].u > m)
break;
v1 += a2[i].u;
u1++;
}
if(!cnt1 || a1[0].u > m){
printf("Case %d: %d %d\n", cas, u1, v1);
continue;
}
for(int i = 0 ; i < cnt1 ; i++){
u2 += a1[i].val;
if(u2 > n) break;
}
v2 = a1[0].u;
u2++;
int temp = u2;
// printf("temp = %d\n", temp);
while(cnt2 > 0 && temp > cnt1)
cnt2--, temp--;
int now1 = 1, now2 = 0;
// printf("cnt1 = %d, cnt2 = %d\n", cnt1, cnt2);
while(now1 < cnt1 && now2 < cnt2){
// printf("v2 = %d\n", v2);
if(v2 + gmin(a1[now1].u, a2[now2].u) > m)
break;
v2 += gmin(a1[now1].u, a2[now2].u);
u2++;
if(u2 > n)
break;
if(a1[now1].u <= a2[now2].u)
cnt2--, now1++;
else
now2++;
}
while(now2 < cnt2){
if(v2 + a2[now2].u > m)
break;
if(u2 > n)
break;
v2 += a2[now2].u;
u2++;
now2++;
}
// printf("u1 = %d, v1 = %d\n", u1, v1);
// printf("u2 = %d, v2 = %d\n", u2, v2);
u2 = gmin(u2, n);
if(u1 > u2){
printf("Case %d: %d %d\n", cas, u1, v1);
}
else if(u1 < u2){
printf("Case %d: %d %d\n", cas, u2, v2);
}
else if(u1 == u2)
printf("Case %d: %d %d\n", cas, u1, gmin(v1, v2));
}
return 0;
}
/*
1
4 5
1 0
2 0
3 0
4 0
*/
相关文章推荐
- 整数的所有因子
- 小球落地
- 级数之和
- 【1】基于ATmega 8A -PU 的蓝牙遥控电源插座设计——【1、总体方案设计】
- 乘法表
- 一元兑换问题
- log4j:WARN No appenders could be found for logger
- 打印机正在打印出错
- allegro中Autosilk top, Silkscreen top 和Assembly top三个什么区别(转)
- Valid Palindrome 解答
- CodeForces 545C Woodcutters (贪心orDP)
- Database Primary key and Foreign key [From Internet]
- SendAnywhere 跨平台传输文件(推荐)
- 核心动画基础动画
- 详解Android中AsyncTask的使用
- 一晃眼这是第六周的实训
- Eclipse中TODO的分类,以及自动去除
- firebug中console命令尝试
- 【特种兵PPT教程】如何用PPT做出08年奥运开幕式卷轴动画效果?
- 【.Net Remoting-1】