Light 1037 - Agent 47 (状态压缩dp)

来源:互联网 发布:四川农大网络教育专业 编辑:程序博客网 时间:2024/05/22 09:51

题意

每次打败一个怪兽可以获得某个手枪。问最少开几枪。

思路

dp[S]表示打败S状态的怪兽最少多少枪。

对于一个状态S,我们枚举有哪些怪兽在里面,然后一一去除,选出打那只怪兽最高攻击力的转移一下。

代码

#include <stack>#include <cstdio>#include <list>#include <cassert>#include <set>#include <fstream>#include <iostream>#include <string>#include <sstream>#include <vector>#include <queue>#include <functional>#include <cstring>#include <algorithm>#include <cctype>//#pragma comment(linker, "/STACK:102400000,102400000")#include <string>#include <map>#include <cmath>//#include <ext/pb_ds/assoc_container.hpp>//#include <ext/pb_ds/hash_policy.hpp>using namespace std;//using namespace __gnu_pbds;#define LL long long#define ULL unsigned long long#define SZ(x) (int)x.size()#define Lowbit(x) ((x) & (-x))#define MP(a, b) make_pair(a, b)#define MS(p, num) memset(p, num, sizeof(p))#define PB push_back#define X first#define Y second#define ROP freopen("input.txt", "r", stdin);#define MID(a, b) (a + ((b - a) >> 1))#define LC rt << 1, l, mid#define RC rt << 1|1, mid + 1, r#define LRT rt << 1#define RRT rt << 1|1#define FOR(i, a, b) for (int i=(a); (i) < (b); (i)++)#define FOOR(i, a, b) for (int i = (a); (i)<=(b); (i)++)#define TRAVERSAL(u, i) for (int i = head[u]; i != -1; i = edge[i].nxt)const double PI = acos(-1.0);const int INF = 0x3f3f3f3f;const double eps = 1e-8;const int MAXN = 1e5+10;const int MOD = 1e9+7;const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };const int seed = 131;int cases = 0;typedef pair<int, int> pii;int dp[1<<16], life[20], n;char atk[20][20];int dfs(int S){    if (dp[S] != INF) return dp[S];    for (int i = 0; i < n; i++) if ((S>>i)&1)  //从哪个状态转移过来    {        int max_atk = 1;        for (int j = 0; j < n; j++)        {            if (j == i || !((S>>j)&1)) continue;            max_atk = max(max_atk, (int)atk[j][i]);        }        dp[S] = min(dp[S], dfs(S^(1<<i))+(life[i]+max_atk-1)/max_atk);    }    return dp[S];}int main(){    //ROP;    int T;    scanf("%d", &T);    while (T--)    {        MS(dp, INF);        dp[0] = 0;        scanf("%d", &n);        for (int i = 0; i < n; i++) scanf("%d", &life[i]);        for (int i = 0; i < n; i++)        {            scanf("%s", atk[i]);            for (int j = 0; j < n; j++) atk[i][j] -= '0';        }        printf("Case %d: %d\n", ++cases, dfs((1<<n)-1));    }    return 0;}
0 0
原创粉丝点击