• Circling Round Treasures(codeforces 375c)


    题意:要求在一张网格图上走出一条闭合路径,不得将炸弹包围进去,使围出的总价值减去路径长度最大。

    /*
      类似于poj3182的做法,只不过出现了多个点,那么就用状态压缩的方法记录一个集合即可。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    char map[25][25],ch[25];
    int n,m,sx,sy,tx,ty,nx,ny,gx[10],gy[10],val[10],w[1010],dp[25][25][1010],cnt=-1,ans;
    int dx[4]={-1,1,0,0};
    int dy[4]={0,0,-1,1};
    struct node{int x,y,k;};
    bool ok(int j){
        if(nx==gx[j]&&ny<gy[j]){
            if(nx>tx)return true;
        }
        else if(tx==gx[j]&&ty<gy[j]){
            if(tx>nx)return true;
        }
        return false;
    }
    void bfs(){
        memset(dp,-1,sizeof(dp));
        queue<node> q;
        node u;u.x=sx;u.y=sy;u.k=0;q.push(u);dp[sx][sy][0]=0;
        while(!q.empty()){
            u=q.front();q.pop();nx=u.x;ny=u.y;int nk=u.k,tk;
            if(nx==sx&&ny==sy)ans=max(ans,w[nk]-dp[nx][ny][nk]);
            for(int i=0;i<4;i++){
                tx=nx+dx[i];ty=ny+dy[i];tk=nk;
                if(tx<1||tx>n||ty<1||ty>m||(map[tx][ty]!='.'&&map[tx][ty]!='S'))continue;
                for(int j=0;j<=cnt;j++)
                    if(ok(j))tk^=(1<<j);
                if(dp[tx][ty][tk]==-1){
                    dp[tx][ty][tk]=dp[nx][ny][nk]+1;
                    node v;v.x=tx;v.y=ty;v.k=tk;q.push(v);
                }
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%s",ch);
            for(int j=1;j<=m;j++){
                map[i][j]=ch[j-1];
                if(map[i][j]=='S')sx=i,sy=j;
                if(map[i][j]>='1'&&map[i][j]<='8'){
                    int t=map[i][j]-'1';++cnt;
                    gx[t]=i;gy[t]=j;
                }
            }
        }
        for(int i=0;i<=cnt;i++)scanf("%d",&val[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]=='B'){
                    ++cnt;gx[cnt]=i;gy[cnt]=j;val[cnt]=-10000;
                }
        for(int i=0;i<(1<<cnt+1);i++)
            for(int j=0;j<=cnt;j++)
                if(i&(1<<j))w[i]+=val[j];
        bfs();
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    个人总结21
    个人总结08
    个人总结07
    构建之法读后感01
    学习进度表 03
    四则运算3
    求最大值
    学习进度表02
    四则运算 2
    学习进度表01
  • 原文地址:https://www.cnblogs.com/harden/p/6391998.html
Copyright © 2020-2023  润新知