[BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa

1294: [SCOI2009]围豆豆Bean

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 458  Solved: 305
[Submit][Status][Discuss]

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。

 

 

从每个豆豆射出一条射线,若经过路线奇数次则说明路线将其包围,若经过偶数次则不包围。

设状态f[i][j][k]表示到达(i,j)围豆豆状态为k的最大价值。

每次枚举起点,用spfa转移即可。

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxn 15
 8 using namespace std;
 9 int tx[5]={1,-1,0,0};
10 int ty[5]={0,0,1,-1};
11 char a[maxn];
12 int num[maxn][maxn];
13 int val[maxn];
14 int n,m,d;
15 int x[maxn],y[maxn];
16 int f[maxn][maxn][600];
17 int inq[maxn][maxn][600];
18 int ans=0;
19 struct data {
20     int x,y,z;
21 }q[10000];
22 void work(int i,int j) {
23     memset(f,-97,sizeof(f));
24     int head=0,tail=1;
25     q[0]=(data){i,j,0};
26     f[i][j][0]=0;
27     while(head!=tail) {
28         data now=q[head++];if(head==9000) head=0;
29         if(now.x==i&&now.y==j) ans=max(ans,f[now.x][now.y][now.z]);
30         for(int k=0;k<4;k++) {
31             int tox=now.x+tx[k],toy=now.y+ty[k],toz=now.z;
32             int add=0;
33             if(tox<1||toy<1||tox>n||toy>m||num[tox][toy]!=0) continue;
34             if(now.x!=tox) {
35                 data temp;
36                 if(tox>now.x) temp=(data){now.x,now.y,now.z};else temp=(data){tox,toy,now.z};
37                 for(int l=1;l<=d;l++) {
38                     if(temp.y>y[l]&&temp.x==x[l]) {
39                         temp.z^=(1<<(l-1));
40                         if(temp.z&(1<<(l-1))) add+=val[l];
41                         else add-=val[l];
42                     }
43                 }
44                 toz=temp.z;
45             }
46             if(f[tox][toy][toz]<f[now.x][now.y][now.z]+add-1){
47                 f[tox][toy][toz]=f[now.x][now.y][now.z]+add-1;
48                 if(!inq[tox][toy][toz]) {
49                     q[tail++]=(data){tox,toy,toz};if(tail==9000) tail=0;
50                     inq[tox][toy][toz]=1;
51                 }
52             }
53             inq[now.x][now.y][now.z]=0;
54         }
55     }
56 }
57 int main() {
58     scanf("%d%d%d",&n,&m,&d);
59     for(int i=1;i<=d;i++) scanf("%d",&val[i]);
60     for(int i=1;i<=n;i++) {
61         scanf("%s",a+1);
62         for(int j=1;j<=m;j++) {
63             if(a[j]=='0') num[i][j]=0;
64             else if(a[j]!='#') x[a[j]-'0']=i,y[a[j]-'0']=j,num[i][j]=-1;
65             else num[i][j]=1;
66         }
67     }
68     for(int i=1;i<=n;i++)
69         for(int j=1;j<=m;j++)
70             if(num[i][j]==0) work(i,j);
71     printf("%d",ans);
72     return 0;
73 }
View Code

 

posted @ 2017-10-23 17:23  wls001  阅读(198)  评论(0编辑  收藏  举报