转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
http://acm.fzu.edu.cn/problem.php?pid=2073
又是一个神题,给出一个n*m的图,上面有若干个怪,每个怪有一定的血,攻击,防御,以及攻击奖励,防御奖励。之后是状态DP,dp[i][j],表示当前位置为i,当前状态为j。
/* ID:cxlove PROB:FJU2073魔塔 DATA:2012.3.27-3.28 HINT:bfs+状态DP */ #include<iostream> #include<cstdio> #include<cstring> #include<vector> #define inf 1<<30 using namespacestd; struct Node{ inthp,attack,defense,award_attack,award_defense; //怪的血量,攻击,防御,攻击奖励,防御奖励 }monster[11]; struct Point{ int x,y; }s,que[500*500+10]; struct Monster{ Point pos; int kind; //记录地图上怪兽的位置和怪物种类 }Map[11]; char str[505][505]; int cnt;//怪兽的个数 int n,m,p; int mat[15][15]; bool flag[505][505]; int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int dp[11][1<<10]; //dp[i][j]表示目前处在第i个怪物的位置,已杀怪物的状态为j时的最少伤害 void bfs(int k){ Point p; inthead=0,tail=0; que[tail++]=Map[k].pos; flag[que[0].x][que[0].y]=true; while(head<tail){ p=que[head++]; for(int i=0;i<4;i++){ Point pp; pp.x=p.x+way[i][0]; pp.y=p.y+way[i][1]; if(str[pp.x][pp.y]!='*'&&pp.x>=0&&pp.x<n&&pp.y>=0&&pp.y<m&&flag[pp.x][pp.y]==false){ if(str[pp.x][pp.y]=='.') que[tail++]=pp; else{ for(int j=1;j<=cnt;j++) if(pp.x==Map[j].pos.x&&pp.y==Map[j].pos.y) mat[k][j]=1; } flag[pp.x][pp.y]=true; } } } } int check(int state,int k){ intper_attack=10,per_deffense=10; //初始攻击,防御 for(int i=0;i<cnt;i++) if((1<<i)&state){ intkind=Map[i+1].kind; per_attack=min(50,monster[kind].award_attack+per_attack); per_deffense=min(50,monster[kind].award_defense+per_deffense); } intkind=Map[k].kind; /*cout<<per_attack<<""<<per_deffense<<endl;*/ if(per_attack<=monster[kind].defense) return-1; if(per_deffense>=monster[kind].attack) return0; inthp=monster[kind].hp,a1=per_attack,d1=monster[kind].defense,a2=monster[kind].attack,d2=per_deffense; return(hp/(a1-d1)+(hp%(a1-d1)==0?-1:0))*(a2-d2); } int sum[1<<10]; vector<int>status[11]; int main(){ sum[0]=0; for(int i=1;i<(1<<10);i++){ sum[i]=sum[i>>1]+(i&1); status[sum[i]].push_back(i); } while(scanf("%d%d%d",&n,&m,&p)!=EOF){ cnt=0; for(int i=1;i<=p;i++) scanf("%d%d%d%d%d",&monster[i].hp,&monster[i].attack,&monster[i].defense,&monster[i].award_attack,&monster[i].award_defense); for(int i=0;i<n;i++){ scanf("%s",str[i]); for(int j=0;j<m;j++) if(str[i][j]=='#'){ s.x=i; s.y=j; } elseif(str[i][j]>='1'&&str[i][j]<='9'){ cnt++; Map[cnt].pos.x=i; Map[cnt].pos.y=j; Map[cnt].kind=str[i][j]-'0'; } } Map[0].pos=s;Map[0].kind=0; memset(mat,0,sizeof(mat)); for(int i=0;i<=cnt;i++){ memset(flag,false,sizeof(flag)); bfs(i); } /*for(inti=0;i<=cnt;i++){ for(int j=0;j<=cnt;j++) printf("%d ",mat[i][j]); printf("\n"); }*/ for(int i=0;i<=cnt;i++) for(int j=0;j<(1<<cnt);j++) dp[i][j]=inf; dp[0][0]=0; for(int i=1;i<=cnt;i++){ if(mat[0][i]){ inttemp=check(0,i); if(temp<0) continue; dp[i][1<<(i-1)]=temp; } } /*for(inti=1;i<=cnt;i++) if(dp[i][1<<(i-1)]!=inf) printf("%d%d\n",i,dp[i][1<<(i-1)]);*/ for(int i=1;i<cnt;i++){ for(int j=0;j<status[i].size();j++){ intJ=status[i][j]; for(int k=1;k<=cnt;k++){ //dp[k][J] if(((1<<(k-1))&J)&&dp[k][J]!=inf){ for(int r=1;r<=cnt;r++){ if(mat[k][r]&&k!=r&&((1<<(r-1))&J)==0){ int temp=check(J,r); /*cout<<k<<" "<<J<<""<<r<<" "<<temp<<endl; system("pause");*/ if(temp<0) continue; dp[r][J|(1<<(r-1))]=min(dp[r][J|(1<<(r-1))],dp[k][J]+temp); for(intrr=1;rr<=cnt;rr++)//注意!!!BFS的时候状态是在原图未消灭一个怪的前提下,注意更新后的情况 if(J&(1<<(rr-1))) dp[rr][J|(1<<(r-1))]=min(dp[rr][J|(1<<(r-1))],dp[r][J|(1<<(r-1))]); } } } } } } int ans=inf; for(int i=1;i<=cnt;i++) ans=min(ans,dp[i][(1<<cnt)-1]); if(ans==inf) printf("-1\n"); else printf("%d\n",ans); } return 0; } /* 1313 6 1012 2 2 1 202 2 2 3 3013 3 1 1 4014 4 1 1 5011 5 1 1 6028 6 1 1 ************* *..121......* ***********.* *.....*...*.* *.5.*.*...*.* **.**.***.*.* *...*..343*.* *.6.*.*****.* **.**.......* *...**.***.** *...*...*.3.* *...*.#.*1..* ************* 513 2 1012 2 2 1 202 2 2 3 ************* *..121......* ***********.* *...#.*...*.* ************* */