http://acm.hdu.edu.cn/showproblem.php?pid=4976

2014 Multi-University Training Contest 10

1006

A simple greedy problem.

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 20    Accepted Submission(s): 4

Problem Description

Victor and Dragon are playing DotA. Bored of normal games, Victor
challenged Dragon with a competition of creep score (CS). In this
competition, there are N enemy creeps for them. They hit the enemy one
after another and Dragon takes his turn first. Victor uses a strong
melee character so that in his turn, he will deal 1 damage to all
creeps. Dragon uses a flexible ranged character and in his turn, he can
choose at most one creep and deal 1 damage. If a creep take 1 damage,
its health will reduce by 1. If a creep’s current health hits zero, it
dies immediately and the one dealt that damage will get one score. Given
the current health of each creep, Dragon wants to know the maximum CS
he can get. Could you help him?
 
Input
The first line of input contains only one integer T(<=70), the number of test cases.

For each case, the first line contains 1 integer, N(<=1000),
indicating the number of creeps. The next line contain N integers,
representing the current health of each creep(<=1000).

 
Output
Each output should occupy one line. Each line should start with "Case
#i: ", with i implying the case number. For each case, just output the
maximum CS Dragon can get.
 
Sample Input
2
5
1 2 3 4 5
5
5 5 5 5 5
 
Sample Output
Case #1: 5
Case #2: 2
 
Source
 
Recommend
hujie   |   We have carefully selected several similar problems for you:  4980 4979 4978 4977 4975

题意:

有n个小兵,编号1~n,血量为ai,均为整数。现在两人轮流补兵,主角先选最多一个兵造成一点伤害(也就是可以不选),然后对手对所有兵造成1点伤害,循环。求主角最多能补多少个兵。兵数<=1000,兵血量<=1000。

题解:先贪心预处理出每个小兵需要主角垫多少刀,然后DP求得最优解。

我们先统计血量为x的小兵有d[x]个,最大血量为ma。这样,如果主角不补刀,第一回合对手会杀完所有1血小兵,第二回合2血,第三回合3血……主角为了补更多的兵,应该使小兵尽量分布在不同的血量。d[x]=0,说明x血量的小兵有0个,这样主角在这个血量的时候就补不到刀,我们需要利用若干个补不到刀的时机来对血量高的小兵进行垫刀,把它的血量削到没有小兵的血量的位置。

从1到最大血量ma扫一遍d[i],若当前d[i]为0,将其下标存入栈中;若大于1,则除了这个血量的时候补的这一刀,还可以将(d[i]-1)个小兵用之前的空闲时机垫刀垫到前面去。最优垫法就是把它垫到之前出现的最后一个d[i]为零的位置,就是我们用栈存的栈顶。

用一个c[i]来记录这个位置应该补的小兵原来在什么位置(主角在第i回合能补到的小兵,本来是多少血)。若d[i]不为0,则c[i]=i;若d[i]为0,按上面说的会在扫的过程中位置被存入栈中,之后d[j]>1的时候栈顶元素会c[i]=j,相当于在第i个回合能补到j血小兵,需要的垫刀次数是(c[i]-i)。

上面说的就是贪心预处理,代码如下:

         int b[],bn=;
mz(c);
int need;
for(i=; i<=ma; i++) {
if(d[i]!=) {
while(d[i]>) {
if(bn>) need=i-b[bn-];///需要need步把它射到最后一个零处,然后还用b[r-1]这1步把它射死
else break;///没有剩余的零就跳出
//printf("i=%d,need=%d,r=%d,l=%d,r-l=%d,b[%d]=%d,b[%d]=%d\n",i,need,r,l,r-l,l+need-1,b[l+need-1],r-1,b[r-1]);
if(need+<=bn) { ///空闲的步数足以把它射到最后一个空格(b[bn-1])处
c[b[bn-]]=i;
bn--;///把这个零用掉
d[i]--;
} else break;///空闲步数不够就跳出
}
c[i]=i;///补这个怪
} else {
b[bn++]=i;///记录零
}
}

然后我们就得到了c[i]这个数组,用它来DP一下就能得到答案。

f[i][j],为AOE杀i血怪前(也就是第i回合),我攻击结束后,我预留攻击还剩下j次,最多杀多少怪(包括i血怪)。

因为c[i]-i为杀这个怪所需的垫刀数,下面这个就是我补这个刀的状态转移。

f[i][j]=max(f[i][j] , f[i-][j+c[i]-i]+);

整个DP如下,还是挺简单的:

         mz(f);
for(i=; i<=ma; i++) {
for(j=; j<=i; j++) {
if(j>)f[i][j]=f[i-][j-];///这次不打,存一个攻击机会
if(c[i]!= && j+c[i]-i < i ) f[i][j]=max(f[i][j] , f[i-][j+c[i]-i]+);///怒把这个小兵打爆
}
}

全代码:

 //#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usll unsigned ll
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) prllf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1biao.out","w",stdout)
#define mp make_pair
#define pb push_back
int n;
int d[];///d[i] i血怪有多少个
int c[];///c[i] 在i位置应该补的怪本来在c[i]位置(本来是个c[i]血怪
int f[][];///f[i][j],AOE杀i血怪前,我攻击结束后,我预留攻击还剩下j次,最多杀多少怪(包括i血怪)
int main() {
int t,n,i,j;
int x;
int cas=;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
mz(d);
int ma=;
REP(i,n) {
scanf("%d",&x);
d[x]++;
ma=max(x,ma);
}
int b[],bn=;
mz(c);
int need;
for(i=; i<=ma; i++) {
if(d[i]!=) {
while(d[i]>) {
if(bn>) need=i-b[bn-];///需要need步把它射到最后一个零处,然后还用b[r-1]这1步把它射死
else break;///没有剩余的零就跳出
//printf("i=%d,need=%d,r=%d,l=%d,r-l=%d,b[%d]=%d,b[%d]=%d\n",i,need,r,l,r-l,l+need-1,b[l+need-1],r-1,b[r-1]);
if(need+<=bn) { ///空闲的步数足以把它射到最后一个空格(b[bn-1])处
c[b[bn-]]=i;
bn--;///把这个零用掉
d[i]--;
} else break;///空闲步数不够就跳出
}
c[i]=i;///补这个怪
} else {
b[bn++]=i;///记录零
}
}
// for(i=1;i<=ma;i++)
// printf("%3d",c[i]);
// puts("");
mz(f);
for(i=; i<=ma; i++) {
for(j=; j<=i; j++) {
if(j>)f[i][j]=f[i-][j-];///这次不打,存一个攻击机会
if(c[i]!= && j+c[i]-i < i ) f[i][j]=max(f[i][j] , f[i-][j+c[i]-i]+);///怒把这个小兵打爆
}
}
int ans=;
for(j=; j<ma; j++)
ans=max(ans,f[ma][j]);
printf("Case #%d: %d\n",cas++,ans);
}
return ;
}

(比赛时第二个看这个题,因为他题目上写着贪心嘛,看起来很水的样子!我也有点思路,写了个贪心,每次把怪垫到之前最后的零的位置,完全没想到这样不是最优……居然还要DP才行,怕了,被题目骗了!)

hdu4976 A simple greedy problem. (贪心+DP)的更多相关文章

  1. HDU 4976 A simple greedy problem. 贪心+DP

    题意: 给定n<=1000个小兵,A每次都能使小兵掉1点血,B每次能使所有小兵掉1点血,A.B轮流攻击,每次轮到A他会选择是否攻击,轮到B必须攻击.求A最多能杀死多少小兵.(当小兵血量为1时被攻 ...

  2. hdu4976 A simple greedy problem.

    A simple greedy problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java ...

  3. HDU 4974 A simple water problem(贪心)

    HDU 4974 A simple water problem pid=4974" target="_blank" style="">题目链接 ...

  4. A simple greedy problem(hdu 4976)

    题意:有n个小兵,每个小兵有a[i]血量,第一个人每次只能对一个小兵砍一滴血,第二个人每次对所有生存的小兵砍一滴血. 最后看第一个人最多可以砍杀几个小兵. /* 首先,如果所有小兵的血量都不同的话,我 ...

  5. hdu4976 贪心+dp

    A simple greedy problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java ...

  6. FZU - 2218 Simple String Problem(状压dp)

    Simple String Problem Recently, you have found your interest in string theory. Here is an interestin ...

  7. hdu 1257 最少拦截系统【贪心 || DP——LIS】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  8. BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

  9. 贪心+dp

    贪心+dp 好多题都是这个思想, 可以说是非常重要了 思想一: 在不确定序列无法dp的情况下, 我们不妨先假设序列已经选定, 而利用贪心使序列达到最优解, 从而先进行贪心排序, 在进行dp选出序列 思 ...

随机推荐

  1. 【BZOJ-4522】密钥破解 数论 + 模拟 ( Pollard_Rho分解 + Exgcd求逆元 + 快速幂 + 快速乘)

    4522: [Cqoi2016]密钥破解 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 290  Solved: 148[Submit][Status ...

  2. C# 调用api的方法

    问题场景: ASP.NET MVC Web API 定义 Post 方法,HttpClient 使用 JsonConvert.SerializeObject 传参进行调用,比如 Web Api 中定义 ...

  3. 负载均衡下的资源文件配置/多站点下的资源文件夹共享(Windows IIS)

    前言: 负载均衡用的是NLB,微软的方案不太靠谱,举个例子吧,AB两台服务器负载出C,如果用户访问访问C之后分配的是A,那么如果A挂了,是不会自动切换到B的.据说后来还有一种NLB的方案可以实现,也不 ...

  4. 洛谷P1726 上白泽慧音

    题目描述 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点.人间 ...

  5. [Android]加密技术

    对称加密无论是加密还是解密都使用同一个key,而非对称加密需要两个key(public key和private key).使用public key对数据进行加密,必须使用private key对数据进 ...

  6. HTML5系列四(WebWorker、地理定位)

    WebWorker简单应用 先从一个简单例子说起,计算数值加法 <script> var worker = new Worker('sumCalculate.js'); worker.on ...

  7. css3之自定义字体

    使用@font-face自定义字体 我们在浏览国外的一些个人网站时,总是可以发现一些非常个性的字体,比如

  8. 之前总结的今天给大分享一下iOS

    退回输入键盘 苹果 ios 开发一年的工作笔记 - (BOOL) textFieldShouldReturn:(id)textField{ [textField resignFirstResponde ...

  9. Log4j、slf4j

    1.Log4j 1.1 Log4j简介 Log4j有三个主要的组件:Loggers(记录器),Appenders (输出位置)和Layouts(布局).这里可简单理解为日志类别,日志要输出的地方和日志 ...

  10. python的简洁是shell无法代替的

    之前线上服务器分发配置都是用shell和expect脚本分发,脚本写了很长,上周换了ansible,现在自己用python写一个,就30行代码就可以实现需求,之前的shell写了快200行了,蛋疼,代 ...