LightOJ - 1037 Agent 47(状压DP)

来源:互联网 发布:php mvc框架 编辑:程序博客网 时间:2024/05/18 03:34

题目大意:有N个敌人,刚开始你有一把枪,每开一枪,可以对敌人造成1点伤害,你杀掉相应的敌人后,可以得到相应敌人的武器。
给你N个敌人的血量,和一个武器伤害矩阵,第i行第j列表示的是第i个敌人的武器,可以对第j个敌人造成1枪val[i][j]的伤害
问至少要开多少枪才能干掉所有的敌人

解题思路:状态压缩,用dp[i]表示干掉i状态下的敌人需要开多少枪

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int N = 20;const int S = (1 << 15) + 10;int n, cas = 1;int life[N], mat[N][N]; int dp[S];char str[N];void init() {    scanf("%d", &n);    for (int i = 0; i < n; i++)        scanf("%d", &life[i]);    for (int i = 0; i < n; i++) {        scanf("%s", str);        for (int j = 0; j < n; j++) {            mat[i][j] = str[j] - '0';        }    }}void solve() {    memset(dp, 0x3f, sizeof(dp));    dp[0] = 0;    queue<int> Q;    Q.push(0);    while (!Q.empty()) {        int s = Q.front();        Q.pop();        if (s == (1 << n) - 1) continue;        for (int i = 0; i < n; i++) {            if (s & (1 << i)) continue;            bool flag = false;            if (dp[s] + life[i] < dp[s | (1 << i)]) {                dp[s | (1 << i)] = dp[s] + life[i];                flag = true;            }            for (int j = 0; j < n; j++) {                if ((s & (1 << j) ) && mat[j][i]) {                    int t = life[i] / mat[j][i];                    t += (life[i] % mat[j][i] ? 1 : 0);                    if (dp[s | (1 << i)] > dp[s] + t) {                        dp[s | (1 << i)] = dp[s] + t;                        flag = true;                    }                }            }            if (flag) Q.push(s | (1 << i));        }    }    printf("Case %d: %d\n", cas++, dp[(1 << n) - 1]);}int main() {    int test;    scanf("%d", &test);    while (test--) {        init();        solve();    }    return 0;}
0 0