1037 - Agent 47

来源:互联网 发布:软件培训老师 编辑:程序博客网 时间:2024/06/05 08:50

题目链接    http://www.lightoj.com/volume_showproblem.php?problem=1037

这道题用到二进制压缩DP D[1<<n],用来保存各种射击状态,每次在射击目标时要判断,

是使用在之前射击过的目标中所获得的枪呢,还是继续使用USP。

#include <stdio.h>#include <string.h>#define N 16#define inf 99999999int d[1<<N];int min(int x,int y){       return x<y?x:y;}int shots(int per,int sum){     int kk;     kk=sum/per;     if(sum%per!=0)     kk++;     return kk;}int main(){int t,ca,n,i,j,k,he[N],cost[N][N];char s;scanf("%d",&t);for(ca=1;ca<=t;ca++){    scanf("%d",&n);    for(i=1;i<=n;i++)         scanf("%d",&he[i]);    getchar();    for(i=1;i<=n;i++)    {         for(j=1;j<=n;j++)            {                scanf("%c",&s);                cost[i][j]=s-'0';            }       getchar();}for(i=1;i<(1<<n);i++)d[i]=inf;         //一开始,,所有的状态都非法for(i=0;i<n;i++)d[1<<i]=he[i+1];   //初始化00000001、00000010、000000100.。。。。等等的状态,表示要变成这种状态所需要的开枪数for(i=1;i<(1<<n);i++){for(j=0;j<n;j++){if(!(i&(1<<j)) && d[i]!=inf) //找到还没有被射击过的目标,并且i状态是合法的{for(k=0;k<n;k++){if(i&(1<<k) && cost[k+1][j+1]>1)   //找到在在之前射击所获得的枪中,是否有对此次射击有用处的。d[i|(1<<j)]=min(d[i|(1<<j)],d[i]+shots(cost[k+1][j+1],he[j+1])); //d[i|(1<<j)] 这个状态可能被更新多次,每次到现在为止最少的射击数。elsed[i|(1<<j)]=min(d[i|(1<<j)],d[i]+he[j+1]);}}}}printf("Case %d: %d\n",ca,d[(1<<n)-1]);}}