您的位置:首页 > 其它

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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: