这题用贪心是很容易过的,直接先杀死对方单位时间输出较高的对象。
这题的动态规划解是将N个敌人压缩到一个int数里面,dp[j] 表示在剩余了j这个数里面所蕴含的敌人的情况下的最大扣血量。
dp方程为 dp[s] = min( dp[s - {bit}] + sumdps[s] * h[bit] ) 其中bit枚举每一位。
代码如下:
#include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; int dp[1200000], N, h[30], dps[30], c[1200000], sum[1200000]; // dp[j] 代表剩余j数字所含二进制位的敌人所扣的最少血量 void dfs(int x, int num, int step, int tot) { if (step == N) { c[x] = num; sum[x] = tot; return; } dfs(x<<1, num, step+1, tot); dfs(x<<1|1, num+1, step+1, tot+dps[N-step]); } void DP() { int lim = 1 << N; for (int i = N-1; i >= 0; --i) { for (int j = 0; j < lim-1; ++j) { if (c[j] == i) { for (int k = 0; k < N; ++k) { if (!(j & (1<<k))) { dp[j] = min(dp[j], dp[j|(1<<k)] + sum[j|(1<<k)] * h[k+1]); } } } } } printf("%d\n", dp[0]); } int main() { while (scanf("%d", &N) == 1) { memset(dp, 0x3f, sizeof (dp)); for (int i = 1; i <= N; ++i) { scanf("%d %d", &dps[i], &h[i]); } dfs(0, 0, 0, 0); dp[(1<<N)-1] = 0; DP(); } return 0; }