题目:你有一个伤害为1的手枪,有n个人你需要去杀害,每个人有血量值h[i],杀害了第i个人你可以获得他的手枪,并用来杀害目标。s[i][j]为第i个人的手枪对第j个人的伤害值。
求最少需要打几枪杀完所有人。
解析:状压DP
S的第i个位表示第i个目标是否已杀害。
状态转移见代码。
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,h[20],dp[1<<20];
char s[20][20];
int sol(){
int i,j,S,Ed,S_,d;
Ed = 1<<n;
for(S = 1;S < Ed;S++) dp[S] = inf;
dp[0] = 0;
for(S = 1;S < Ed;S++){
for(i = 0;i < n;i++){
if(!(S>>i&1)) continue;
S_ = S^(1<<i);
dp[S] = min(dp[S],dp[S_]+h[i]);
for(j = 0;j < n;j++){
if(!(S_>>j&1)) continue;
d = s[j][i]-'0';
if(d) dp[S] = min(dp[S],dp[S_]+(int)ceil(1.0*h[i]/d));
}
}
}
return dp[Ed-1];
}
int main(){
int i,j,t,cas,T;
scanf("%d",&cas);
for(T = 1;T <= cas;T++){
scanf("%d",&n);
for(i = 0;i < n;i++) scanf("%d",&h[i]);
for(i = 0;i < n;i++) scanf("%s",s[i]);
printf("Case %d: %d\n",T,sol());
}
return 0;
}