BZOJ1294: [SCOI2009]围豆豆Bean

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1294

状压dp,dis[s][i][j]表示从(i,j)出发围的状态是s的最短路。

然后判断一个点是否在区间内用射线法(向右射出一条射线,如果穿过的边界是奇数就算,偶数则不算。

然后枚举起点跑最短路就可以了。

(傻叉错误调半天TAT

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<queue>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
using namespace std;
struct data{int x,y,z;
};
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int mp[15][15],dis[1101][15][15],d[1101][15][15],vis[1101][15][15],v[15],p[15][2],bin[15];
int n,m,D,tot,ans;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int get(int s,int x,int y,int xx,int yy){
    int ans=s;
    rep(i,1,D) {
        int nowx=p[i][0],nowy=p[i][1];
        if (yy>nowy&&((x<=nowx&&xx>nowx)||(x>nowx&&xx<=nowx))) ans=ans^bin[i-1];
    }
    return ans;
}
void spfa(int x,int y){
    queue<data> q;
    clr(dis,127); clr(vis,0); dis[0][x][y]=0; q.push((data){x,y,0}); 
    while (!q.empty()){
        data u=q.front(); q.pop(); vis[u.z][u.x][u.y]=1;
        rep(i,0,3){
            int vx=u.x+dx[i],vy=u.y+dy[i];
            if (mp[vx][vy]!=0) continue;
            int tmp=get(u.z,u.x,u.y,vx,vy);
            if (dis[tmp][vx][vy]>dis[u.z][u.x][u.y]+1) {
                dis[tmp][vx][vy]=dis[u.z][u.x][u.y]+1;
                if (!vis[tmp][vx][vy]){
                    vis[tmp][vx][vy]=1;
                    q.push((data){vx,vy,tmp});
                }
            }
        }
        vis[u.z][u.x][u.y]=0;
    }
    rep(i,0,(1<<D)-1) {
        int tmp=-dis[i][x][y];
        rep(j,1,D) if (i&bin[j-1]) tmp+=v[j];
        ans=max(ans,tmp);    
    }
}
int main(){
    bin[0]=1; rep(i,1,10) bin[i]=bin[i-1]*2;
    n=read(); m=read();
    D=read();
    rep(i,1,D) v[i]=read();
    clr(mp,-1);
    rep(i,1,n) rep(j,1,m){
        char ch=getchar(); while (!isdigit(ch)&&ch!='#') ch=getchar();
        if (ch=='#') continue;
        else mp[i][j]=ch-'0';
        if (ch!='0') p[ch-'0'][0]=i,p[ch-'0'][1]=j;
    }
    ans=0;    
    rep(i,1,n) rep(j,1,m) 
        if (mp[i][j]==0)spfa(i,j);
    printf("%d\n",ans);
    return 0;
}

 

posted on 2015-12-10 21:06  ctlchild  阅读(286)  评论(0编辑  收藏  举报

导航