[SCOI2009]围豆豆
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。
这个博客有详细图片和解析
http://blog.csdn.net/Phenix_2015/article/details/50739989
问题在于如何判断一个豆子是否在多边形内。
实际上有一个很好判断的方法,那就是可以引一条水平射线,看和多边形有几个交点,有奇数个交点就在多边形内,否则在多边形外。
这样状态压缩,对于一个状态,肯定步数越少越好,然后就可以更据压缩的状态,做分层图最短路
每走一步就可以更新当前状态
但还有一种情况,在偶数个交点时也有可能被围起来。
如下图所示:
那么转移的过程中,显然水平方向的移动是不影响答案的,只有竖直方向的移动才会影响到点的位置
特殊情况把每一条线段假设成上端为开下端为闭的线段,即只有下断点与射线相交才会有用,那么这样同向的线段就只会被算一次了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 struct ZYYS 9 { 10 int x,y,s; 11 }; 12 const int dx[4]={0,0,1,-1}; 13 const int dy[4]={1,-1,0,0}; 14 int d,px[101],py[101],n,m,val[11],ans; 15 int dist[11][11][513],inf; 16 bool vis[11][11][513]; 17 char ss[11][11]; 18 int cross(int sx,int sy,int x,int y,int s) 19 {int i; 20 int p=max(sy,y); 21 for (i=1;i<=d;i++) 22 if (py[i]==p&&px[i]<x) 23 s^=(1<<i-1); 24 return s; 25 } 26 void spfa(int sx,int sy) 27 {int i,j; 28 queue<ZYYS>Q; 29 memset(dist,127/2,sizeof(dist)); 30 inf=dist[0][0][0]; 31 memset(vis,0,sizeof(vis)); 32 Q.push((ZYYS){sx,sy,0}); 33 dist[sx][sy][0]=0; 34 while (Q.empty()==0) 35 { 36 ZYYS u=Q.front(); 37 Q.pop(); 38 vis[u.x][u.y][u.s]=0; 39 for (i=0;i<4;i++) 40 { 41 int x=u.x+dx[i],y=u.y+dy[i]; 42 if (x<1||x>n||y<1||y>m) continue; 43 if (ss[x][y]=='#'||ss[x][y]!='0') continue; 44 int s=u.s; 45 if (i<=1) 46 s=cross(u.x,u.y,x,y,s); 47 if (dist[x][y][s]>dist[u.x][u.y][u.s]+1) 48 { 49 dist[x][y][s]=dist[u.x][u.y][u.s]+1; 50 if (vis[x][y][s]==0) 51 { 52 vis[x][y][s]=1; 53 Q.push((ZYYS){x,y,s}); 54 } 55 } 56 } 57 } 58 for (i=0;i<=(1<<d)-1;i++) 59 { 60 int res=-dist[sx][sy][i]; 61 for (j=1;j<=d;j++) 62 if (i&(1<<j-1)) res+=val[j]; 63 ans=max(ans,res); 64 } 65 } 66 int main() 67 {int i,j; 68 cin>>n>>m>>d; 69 for (i=1;i<=d;i++) 70 { 71 scanf("%d",&val[i]); 72 } 73 for (i=1;i<=n;i++) 74 { 75 scanf("%s",ss[i]+1); 76 for (j=1;j<=m;j++) 77 { 78 if (ss[i][j]>'0'&&ss[i][j]<='9') 79 px[ss[i][j]-'0']=i,py[ss[i][j]-'0']=j; 80 } 81 } 82 for (i=1;i<=n;i++) 83 { 84 for (j=1;j<=m;j++) 85 if (ss[i][j]=='0') 86 { 87 spfa(i,j); 88 } 89 } 90 cout<<ans; 91 }