杀手47游戏背景,有n个目标要杀死,初始手枪一次射击对敌人造成一点伤害,可以用杀死过的敌人的武器杀敌,dps[i][j]是第i个人的武器对第j个人的伤害,问杀完目标需要开多少枪。
范围15,状压DP标准范围...
dp[i]代表杀完i状态的人后最少的开枪数,那么杀死一个新的目标j,也就是说i&(1<<j)==0的目标,我们要判断是否要用到i状态下已经收集的武器谁打j最厉害...收集到的武器状态就是i&(1<<k)!=0...
忘记输出case,找了半天错都没找到...还以为有什么神坑..
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1<<30
int dp[(1<<15)+10];
int hp[20];
int dps[20][20];
char s[20];
int pd(int x,int y)
{
if(dps[x][y]==0)
return inf;
int ans=0;
ans=hp[y]/dps[x][y];
if(hp[y]%dps[x][y])
ans++;
return ans;
}
int main()
{
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
int n;
scanf("%d",&n);
memset(dp,127,sizeof(dp));
memset(dps,0,sizeof(dps));
for(int i=0;i<n;i++)
{
scanf("%d",&hp[i]);
dp[1<<i]=hp[i];
}
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;s[j];j++)
{
dps[i][j]=s[j]-'0';
}
}
for(int i=1;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if(i&(1<<j)) continue;
dp[i|(1<<j)]=min(dp[i]+hp[j],dp[i|(1<<j)]);
for(int k=0;k<n;k++)
{
if(i&(1<<k))
{
int tmp=pd(k,j);
dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+tmp);
}
}
}
}
printf("Case %d: %d\n",cas,dp[(1<<n)-1]);
}
return 0;
}