HDU 4976 A simple greedy problem. 贪心+DP

题意:

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

思路:

  如果所有小兵血量都不一样,A必定能杀死所有小兵。如果有小兵血量相同,那么A必定会攻击一些小兵使他们血量不同。所以我们可以把A的攻击分为两类:用来刚好杀死小兵的一次, 和用来使小兵血量不同的攻击。

  我们可以用贪心的思想预处理出怎样用最小的攻击次数让小兵的血量都不同。

  然后我们可以用DP[i][j]表示在B第 i 次攻击的时候A攻击了 j 次时,A能杀死的最多小兵数量。这样,A没有攻击的次数,可以留到后面,让后面的小兵血量变得不同。

代码:

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <queue>
 9 #include <stack>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <functional>
14 #include <cctype>
15 #include <time.h>
16
17 using namespace std;
18
19 const int INF = 1<<30;
20 const int MAXN = 1055;
21
22 int a[MAXN];
23 int b[MAXN];
24 int dp[MAXN];
25 int n, MAX;
26
27 void solve() {
28     scanf("%d", &n);
29     for (int i = 0; i < n; i++) scanf("%d", &a[i]);
30     sort(a, a+n);
31     memset(b, 0, sizeof(b));
32     for (int i = 0; i < n; i++)
33         for (int j = a[i]; j > 0; j--)
34             if (!b[j]) {
35                 b[j] = a[i];
36                 break;
37             }
38     memset(dp, 0, sizeof(dp));
39     for (int i = 1; i <= a[n-1]; i++) if (b[i]>0) {
40         for (int j = i; j >= b[i]-i+1; j--) {
41             dp[j] = max(dp[j], dp[j-b[i]+i-1]+1);
42         }
43     }
44     int ans = 0;
45     for (int i = 0; i <= a[n-1]; i++)
46         ans = max(ans, dp[i]);
47     printf("%d\n", ans);
48 }
49
50 int main() {
51     #ifdef Phantom01
52         freopen("HDU4976.txt", "r", stdin);
53     #endif //Phantom01
54
55     int T;
56     scanf("%d", &T);
57     for (int i = 1; i <= T; i++) {
58         printf("Case #%d: ", i);
59         solve();
60     }
61
62     return 0;
63 }

时间: 2024-12-22 14:38:10

HDU 4976 A simple greedy problem. 贪心+DP的相关文章

hdu 4976 A simple greedy problem.

题意: 有n个小兵,每一个小兵有a[i]血量,第一个人每次仅仅能对一个小兵砍一滴血,第二个人每次对全部生存的小兵砍一滴血.最后看第一个人最多能够砍杀几个小兵. 思路: 这个就是游戏中所说的垫刀问题.首先是不一样的越多那么第一个人所补得刀数就越多. 那么就要考虑要多少刀把当前的小兵的血量砍得和别人不一样. 用W[i]表示砍了i刀之后与其它的血量不一样的原始血量 用dp[i][j],表示进行了i组攻击(第一个攻击一次,第二个攻击一次,称为一组).第一个留有j次攻击,最多能杀死的小兵数目. 那么在第i

HDU 4974 A simple water problem(贪心)

HDU 4974 A simple water problem 题目链接 签到题,很容易贪心得到答案是(sum + 1) / 2和ai最大值的最大值 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 100005; typedef long long ll; int t, n; ll a, Max, sum; int main(

HDU - 4974 A simple water problem

Problem Description Dragon is watching competitions on TV. Every competition is held between two competitors, and surely Dragon's favorite. After each competition he will give a score of either 0 or 1 for each competitor and add it to the total score

hdu 4974 A simple water problem(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4974 Problem Description Dragon is watching competitions on TV. Every competition is held between two competitors, and surely Dragon's favorite. After each competition he will give a score of either 0 or

2014多校第十场1004 || HDU 4974 A simple water problem

题目链接 题意 : n支队伍,每场两个队伍表演,有可能两个队伍都得一分,也可能其中一个队伍一分,也可能都是0分,每个队伍将参加的场次得到的分数加起来,给你每个队伍最终得分,让你计算至少表演了几场. 思路 : ans = max(maxx,(sum+1)/2) :其实想想就可以,如果所有得分中最大值没有和的一半大,那就是队伍中一半一半对打,否则的话最大的那个就都包了. 1 #include <cstdio> 2 #include <cstring> 3 #include <st

hdu 1757 A Simple Math Problem (乘法矩阵)

A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2441    Accepted Submission(s): 1415 Problem Description Lele now is thinking about a simple function f(x).If x < 10 f(x) =

hdu4976 A simple greedy problem.

A simple greedy problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 476    Accepted Submission(s): 193 Problem Description Victor and Dragon are playing DotA. Bored of normal games, Victor

HDU 4939 Stupid Tower Defense(贪心+dp)

HDU Stupid Tower Defense 题目链接 题意:有一些塔,红塔能攻击经过他的,绿塔能攻击经过之后的,蓝塔能把经过之后的减速,求在1-n上放塔,求伤害最大值 思路:一开始以为直接贪心,绿塔最前,蓝塔中间,红塔最后就可以了,结果其实是错的 不过,红塔放最后是肯定的,这个很显然就不多证明了,是贪心的思想 然后就dp[i][j]表示放到i,前面有j个绿塔去状态转移即可 代码: #include <cstdio> #include <cstring> #include &l

HDU 4974 A simple water problem 模拟(水

水题. #include <cstdio> #include <iostream> #include <queue> #include <algorithm> using namespace std; typedef long long ll; priority_queue<int> q; int main() { int T, cas = 0; scanf("%d", &T); while(T-- > 0) {