HDU4310 Hero 贪心Or动态规划

这题用贪心是很容易过的,直接先杀死对方单位时间输出较高的对象。

这题的动态规划解是将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;
}
原文地址:https://www.cnblogs.com/Lyush/p/2611040.html