[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。

这个博客有详细图片和解析

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 }

 

posted @ 2018-01-12 21:19  Z-Y-Y-S  阅读(395)  评论(0编辑  收藏  举报