【GDOI2016模拟3.15】圈地游戏

SOL:

  BFS式dp。

#include<bits/stdc++.h>
using namespace std;
struct state{int x,y,z;state(){}state(int _x,int _y,int _z):x(_x),y(_y),z(_z){}}X;
queue<state> Q;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int x,y,anw,sp,sta[18],ans,f[23][23][1<<8|1],n,m,p[23][23],val[18],px,ox[18],oy[18],xoxo;
char s[27][27];
void sol(int i) { 
    anw=0;
    for (int j=0;j<sp;j++)
      if ((i>>j)&1) {if (sta[j]==-1) return; 
       anw+=val[sta[j]];
    }
    ans=max(ans,anw-f[x][y][i]);
}
void dowork() {
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++) 
      if (s[i][j]=='B'||isdigit(s[i][j])) 
       (sta[sp]=(isdigit(s[i][j])?px++,s[i][j]-48:-1)),ox[sp]=i,oy[sp++]=j;
      else if (s[i][j]=='S') x=i,y=j;
    for (int i=1;i<=px;i++) scanf("%d",val+i);
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++)
      for (int k=0;k<sp;k++) 
       if (i<ox[k]&&j==oy[k]) p[i][j]|=1<<k;
}
int top;
signed main () {
//    freopen("2.in","r",stdin);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
    dowork();
    memset(f,127,sizeof f);
    f[x][y][0]=0; Q.push(state(x,y,0));
    while (!Q.empty()) {
        X=Q.front(); Q.pop();
//        if (X.x==5&&X.y==1&&X.z==13) {
//            top=0;
//        }
//        cout<<X.x<<' '<<X.y<<' '<<X.z<<endl;
        for (int i=0;i<4;i++) {
            int nx=X.x+dx[i], ny=X.y+dy[i];
            if (s[nx][ny]!='.'&&s[nx][ny]!='S') continue;
            if (nx<1||nx>n||ny<1||ny>m) continue;
            xoxo=X.z;
            if (i==1) xoxo=X.z^p[X.x][X.y];
            if (i==3) xoxo=X.z^p[nx][ny];
            if (f[nx][ny][xoxo]>f[X.x][X.y][X.z]+1) {
                f[nx][ny][xoxo]=f[X.x][X.y][X.z]+1;
                Q.push(state(nx,ny,xoxo));
//                if (++top<30) cout<<"exd"<<nx<<' '<<ny<<' '<<xoxo<<endl;
            }
        }
    }
    for (int i=0;i<(1<<sp);i++)  sol(i);
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/rrsb/p/9335821.html