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

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 }

 

posted @ 2017-10-24 22:29  wfj_2048  阅读(293)  评论(0编辑  收藏  举报