Bzoj1294 [SCOI2009]围豆豆Bean
Submit: 412 Solved: 276
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。
Source
数学 几何 状态压缩 BFS
从一点向随机方向引一条射线,如果射线和多边形的边相交奇数次,说明点在多边形内。
据此我们可以搞D条射线出来,用来判断D个点当前是否已经被圈进来。
f[x][y][圈进的豆豆集合S]=最小花费
状压BFS,在搜索过程中即时更新点被圈的状态,方便剪枝(暴力搜完再判断收益会T)
写了SPFA,差不多一个意思
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 using namespace std; 10 const int mx[5]={0,0,1,0,-1}; 11 const int my[5]={0,1,0,-1,0}; 12 const int INF=0x3f3f3f3f; 13 const int mxn=100010; 14 int read(){ 15 int x=0,f=1;char ch=getchar(); 16 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 17 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 struct point{ 21 int cx,cy;//点 22 int x,y;//向量 23 point operator + (point b){return (point){x+b.x,y+b.y};} 24 point operator - (point b){return (point){x-b.x,y-b.y};} 25 int operator * (point b){return x*b.x+y*b.y;} 26 }; 27 typedef point Vector; 28 Vector b[mxn]; 29 double Cross(point a,point b){ 30 return a.x*b.y-a.y*b.x; 31 } 32 int n,m,D; 33 int Segcross(int x,int y,int nx,int ny,int S){ 34 for(int i=1;i<=D;i++){ 35 if(( (x<b[i].cx && nx>=b[i].cx)||(x>=b[i].cx && nx<b[i].cx) )&& y>b[i].cy){ 36 S^=1<<(i-1); 37 } 38 } 39 return S; 40 } 41 int w[mxn]; 42 char mp[12][12]; 43 struct node{int i,j,S;}; 44 int f[12][12][1<<9],ans; 45 bool inq[12][12][1<<9]; 46 void SPFA(int sx,int sy){ 47 queue<node>q; 48 q.push((node){sx,sy,0}); 49 memset(f,0x3f,sizeof f); 50 f[sx][sy][0]=0; 51 while(!q.empty()){ 52 node u=q.front();q.pop(); 53 inq[u.i][u.j][u.S]=0; 54 for(int k=1;k<=4;k++){ 55 int nx=u.i+mx[k],ny=u.j+my[k]; 56 if(nx>0 && nx<=n && ny>0 && ny<=m){ 57 if(mp[nx][ny]!='0')continue; 58 int s=Segcross(u.i,u.j,nx,ny,u.S); 59 if(f[nx][ny][s]>f[u.i][u.j][u.S]+1){ 60 f[nx][ny][s]=f[u.i][u.j][u.S]+1; 61 inq[nx][ny][s]=1; 62 q.push((node){nx,ny,s}); 63 } 64 } 65 } 66 } 67 int ed=1<<D; 68 // printf("sx:%d sy:%d\n",sx,sy); 69 for(int i=0;i<ed;i++){ 70 // printf("S:%d f:%d\n",i,f[sx][sy][i]); 71 int res=-f[sx][sy][i]; 72 for(int j=1;j<=D;j++){ 73 if(i&(1<<(j-1)))res+=w[j]; 74 } 75 ans=max(ans,res); 76 } 77 return; 78 } 79 int main(){ 80 // freopen("in.txt","r",stdin); 81 int i,j; 82 n=read();m=read();D=read(); 83 for(i=1;i<=D;i++)w[i]=read(); 84 for(i=1;i<=n;i++){ 85 scanf("%s",mp[i]+1); 86 for(j=1;j<=m;j++){ 87 if(mp[i][j]>'0' && mp[i][j]<='9'){ 88 int x=mp[i][j]-'0'; 89 b[x]=(Vector){i,j,0,j+100}; 90 } 91 } 92 } 93 /* for(i=1;i<=D;i++){ 94 printf("%d %d %d %d\n",b[i].cx,b[i].cy,b[i].x,b[i].y); 95 }*/ 96 // 97 for(i=1;i<=n;i++) 98 for(j=1;j<=m;j++) 99 if(mp[i][j]=='0'){ 100 SPFA(i,j); 101 } 102 printf("%d\n",ans); 103 return 0; 104 }
本文为博主原创文章,转载请注明出处。