bzoj1294 [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。
正解:计算几何+状压$dp$+$spfa$。
这题的难点就在于如何判断一个豆子是否在多边形内。
实际上有一个很好判断的方法,那就是可以引一条水平线,看和多边形有几个交点,有奇数个交点就在多边形内,否则在多边形外。
但是还有一个情况。就是如果路径从上往下,突然往水平拐,再往下拐,那么这是有偶数个交点的,但是豆子还是在多边形内。
不过我们可以把所有边当成上开下闭的边,只有当水平线与一条边的下端点相交才算进去。
然后我们可以直接写一个状压+$spfa$。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define inf (1<<29) 6 7 using namespace std; 8 9 struct data{ int x,y,bin; }p[15]; 10 11 const int d1[4]={0,0,-1,1}; 12 const int d2[4]={-1,1,0,0}; 13 14 int f[15][15][1<<12],vis[15][15][1<<12],g[15][15],val[15],S,n,m,all,ans; 15 16 queue<data> Q; 17 18 il int gi(){ 19 RG int x=0,q=1; RG char ch=getchar(); 20 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 21 if (ch=='-') q=-1,ch=getchar(); 22 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 23 return q*x; 24 } 25 26 il char gc(){ 27 RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='#') ch=getchar(); 29 return ch; 30 } 31 32 il void spfa(RG int sx,RG int sy){ 33 for (RG int i=1;i<=n;++i) 34 for (RG int j=1;j<=m;++j) 35 for (RG int k=0;k<all;++k) f[i][j][k]=-inf; 36 Q.push((data){sx,sy,0}),f[sx][sy][0]=0,vis[sx][sy][0]=1; 37 while (!Q.empty()){ 38 RG data now=Q.front(); Q.pop(); 39 if (now.x==sx && now.y==sy) 40 ans=max(ans,f[now.x][now.y][now.bin]); 41 for (RG int k=0,x,y,yy,bin,del;k<4;++k){ 42 x=now.x+d1[k],y=now.y+d2[k]; 43 if (x<=0 || x>n || y<=0 || y>m || g[x][y]) continue; 44 bin=now.bin,yy=max(y,now.y),del=0; 45 if (k<=1){ 46 for (RG int i=1;i<=S;++i) 47 if (p[i].y==yy && p[i].x<x){ 48 bin^=1<<(i-1); 49 if (bin>>(i-1)&1) del+=val[i]; else del-=val[i]; 50 } 51 } 52 if (f[x][y][bin]<f[now.x][now.y][now.bin]+del-1){ 53 f[x][y][bin]=f[now.x][now.y][now.bin]+del-1; 54 if (!vis[x][y][bin]) vis[x][y][bin]=1,Q.push((data){x,y,bin}); 55 } 56 } 57 vis[now.x][now.y][now.bin]=0; 58 } 59 return; 60 } 61 62 int main(){ 63 #ifndef ONLINE_JUDGE 64 freopen("bean.in","r",stdin); 65 freopen("bean.out","w",stdout); 66 #endif 67 n=gi(),m=gi(),S=gi(),all=1<<S; 68 for (RG int i=1;i<=S;++i) val[i]=gi(); 69 for (RG int i=1;i<=n;++i) 70 for (RG int j=1;j<=m;++j){ 71 RG char ch=gc(); 72 if (ch=='#') g[i][j]=-1; else g[i][j]=ch-'0'; 73 if (g[i][j]>=1 && g[i][j]<=9) p[g[i][j]]=(data){i,j}; 74 } 75 for (RG int i=1;i<=n;++i) 76 for (RG int j=1;j<=m;++j) if (!g[i][j]) spfa(i,j); 77 cout<<ans; return 0; 78 }