[BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa
Posted wls001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa相关的知识,希望对你有一定的参考价值。
1294: [SCOI2009]围豆豆Bean
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 458 Solved: 305
[Submit][Status][Discuss]
Description
Input
第一行两个整数N和M,为矩阵的边长。 第二行一个整数D,为豆子的总个数。 第三行包含D个整数V1到VD,分别为每颗豆子的分值。 接着N行有一个N×M的字符矩阵来描述游戏矩阵状态,0表示空格,#表示障碍物。而数字1到9分别表示对应编号的豆子。
Output
仅包含一个整数,为最高可能获得的分值。
Sample Input
3 8
3
30 -100 30
00000000
010203#0
00000000
3
30 -100 30
00000000
010203#0
00000000
Sample Output
38
HINT
50%的数据满足1≤D≤3。
100%的数据满足1≤D≤9,1≤N, M≤10,-10000≤Vi≤10000。
从每个豆豆射出一条射线,若经过路线奇数次则说明路线将其包围,若经过偶数次则不包围。
设状态f[i][j][k]表示到达(i,j)围豆豆状态为k的最大价值。
每次枚举起点,用spfa转移即可。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define maxn 15 8 using namespace std; 9 int tx[5]={1,-1,0,0}; 10 int ty[5]={0,0,1,-1}; 11 char a[maxn]; 12 int num[maxn][maxn]; 13 int val[maxn]; 14 int n,m,d; 15 int x[maxn],y[maxn]; 16 int f[maxn][maxn][600]; 17 int inq[maxn][maxn][600]; 18 int ans=0; 19 struct data { 20 int x,y,z; 21 }q[10000]; 22 void work(int i,int j) { 23 memset(f,-97,sizeof(f)); 24 int head=0,tail=1; 25 q[0]=(data){i,j,0}; 26 f[i][j][0]=0; 27 while(head!=tail) { 28 data now=q[head++];if(head==9000) head=0; 29 if(now.x==i&&now.y==j) ans=max(ans,f[now.x][now.y][now.z]); 30 for(int k=0;k<4;k++) { 31 int tox=now.x+tx[k],toy=now.y+ty[k],toz=now.z; 32 int add=0; 33 if(tox<1||toy<1||tox>n||toy>m||num[tox][toy]!=0) continue; 34 if(now.x!=tox) { 35 data temp; 36 if(tox>now.x) temp=(data){now.x,now.y,now.z};else temp=(data){tox,toy,now.z}; 37 for(int l=1;l<=d;l++) { 38 if(temp.y>y[l]&&temp.x==x[l]) { 39 temp.z^=(1<<(l-1)); 40 if(temp.z&(1<<(l-1))) add+=val[l]; 41 else add-=val[l]; 42 } 43 } 44 toz=temp.z; 45 } 46 if(f[tox][toy][toz]<f[now.x][now.y][now.z]+add-1){ 47 f[tox][toy][toz]=f[now.x][now.y][now.z]+add-1; 48 if(!inq[tox][toy][toz]) { 49 q[tail++]=(data){tox,toy,toz};if(tail==9000) tail=0; 50 inq[tox][toy][toz]=1; 51 } 52 } 53 inq[now.x][now.y][now.z]=0; 54 } 55 } 56 } 57 int main() { 58 scanf("%d%d%d",&n,&m,&d); 59 for(int i=1;i<=d;i++) scanf("%d",&val[i]); 60 for(int i=1;i<=n;i++) { 61 scanf("%s",a+1); 62 for(int j=1;j<=m;j++) { 63 if(a[j]==‘0‘) num[i][j]=0; 64 else if(a[j]!=‘#‘) x[a[j]-‘0‘]=i,y[a[j]-‘0‘]=j,num[i][j]=-1; 65 else num[i][j]=1; 66 } 67 } 68 for(int i=1;i<=n;i++) 69 for(int j=1;j<=m;j++) 70 if(num[i][j]==0) work(i,j); 71 printf("%d",ans); 72 return 0; 73 }
以上是关于[BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa
BZOJ1294[SCOI2009]围豆豆Bean 射线法+状压DP+SPFA