Bzoj1294 [SCOI2009]围豆豆Bean

Time Limit: 10 Sec  Memory Limit: 162 MB
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

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 }

 

posted @ 2017-04-05 15:29  SilverNebula  阅读(202)  评论(0编辑  收藏  举报
AmazingCounters.com