一道状态压缩的dp题, 在进行状态转移时, for循环找到未被杀死的目标进行攻击, 再一个for循环从杀死的目标中找到对目标杀伤力最大的枪即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = (1<<15) + 10;
const int inf = 99999999;
int dp[20][maxn], cost[20][20], a[20];
char s[20];
int shot(int h, int k)
{
int sum;
sum = a[k]/h;
if(a[k]%h)
sum++;
return sum;
}
int main()
{
int t, ca = 1;
scanf("%d", &t);
while(t--)
{
int n, m;
scanf("%d", &n);
m = (1<<n) - 1;
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
getchar();
for(int i=1; i<=n; i++)
{
scanf("%s", s+1);
for(int j=1; j<=n; j++)
cost[i][j] = s[j] - '0';
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
dp[i][j] = inf;
for(int i=1; i<=n; i++)
dp[1][1<<n>>i] = a[i];
for(int i=2; i<=n; i++)
for(int j=1; j<=m; j++)
if(dp[i-1][j] < inf)
{
for(int k=1; k<=n; k++)
if(!((1<<n>>k) & j))
{
int h = 1;
for(int l=1; l<=n; l++)
if((1<<n>>l) & j)
h = max(h, cost[l][k]); //找杀伤力最大的枪
dp[i][(1<<n>>k) | j] = min(dp[i][(1<<n>>k) | j], dp[i-1][j] + shot(h, k));
}
}
printf("Case %d: %d\n", ca++, dp[n][m]);
}
return 0;
}