ZOJ - 3611——Ice Valley

題意:找到一個地圖中儘量多的寶藏並在儘可能短的時間內走到指定地點。
思路:狀態壓縮。先預處理出每個寶藏之間的距離,然後狀壓dp。寫代碼的時候又犯了把變量名寫錯的錯誤。。導致re。
代碼如下:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<map>
#include<set>
#include<list>
#include<stack>
#include<algorithm>
#include<queue>
#include<vector>
#include<time.h>
#include<iomanip>
//#include<assert.h>
using namespace std;

const int dir[4][2] = {-1,0,0,1,1,0,0,-1};

int n,m;
char g[505][505];
int dis[20][20];
int id[505][505];
int xx[20];
int yy[20];
int tot;
int x1,y1,x2,y2;
bool vis[505][505];

int dist[505][505];

struct Pos
{
    int x,y;
    Pos(int x,int y):x(x),y(y){}
};

bool judge(int x,int y)
{
    if(x<0||x>=n)return false;
    if(y<0||y>=m)return false;
    return true;
}

void bfs(int tid,Pos s)
{
    memset(dist ,-1,sizeof(dist));
    memset(vis,0,sizeof(vis));
    dist[s.x][s.y] = 0;
    if(id[s.x][s.y]>=0){
        dis[tid][id[s.x][s.y]] =dis[id[s.x][s.y]][tid]= 0;
    }
    queue<Pos> q;
    q.push(s);
    vis[s.x][s.y] = 1;
    while(!q.empty()){
        s = q.front();
        q.pop();
        vis[s.x][s.y] = 0;
        if(g[s.x][s.y] == '0'||g[s.x][s.y] == '$'){
            for(int i = 0 ;i<4;++i){
                int tx = s.x + dir[i][0];
                int ty = s.y + dir[i][1];
//                assert(tx == s.x+dir[i][0]);
//                assert(ty == s.y + dir[i][1]);
                if(!judge(tx,ty))continue;
                if(g[tx][ty] == '#'||g[tx][ty] == 'W')continue;
                if(dist[tx][ty] == -1||dist[tx][ty] > dist[s.x][s.y] + 1){
                    dist[tx][ty] = dist[s.x][s.y] + 1;
                    if(!vis[tx][ty]){
                        q.push(Pos(tx,ty));
                        vis[tx][ty] = 1;
                    }
                    if(id[tx][ty] >=0) dis[tid][id[tx][ty]] = dist[tx][ty];
                }
            }
            continue;
        }
        Pos nxt = s;
        if(g[s.x][s.y] == 'L'){
            nxt.y--;
        } else if(g[s.x][s.y] == 'R'){
            nxt.y++;
        } else if(g[s.x][s.y] == 'U'){
            nxt.x--;
        } else if(g[s.x][s.y] == 'D'){
            nxt.x++;
        }
        int tx = nxt.x;int ty = nxt.y;
        if(!judge(nxt.x,nxt.y))continue;
        if(g[nxt.x][nxt.y]=='#'||g[nxt.x][nxt.y] == 'W')continue;
        if(dist[tx][ty] == -1||dist[tx][ty] > dist[s.x][s.y] + 1){
            dist[tx][ty] = dist[s.x][s.y] + 1;
            if(!vis[nxt.x][nxt.y]){
                vis[nxt.x][nxt.y] = 1;
                q.push(nxt);
            }
            if(id[tx][ty] >=0) dis[tid][id[tx][ty]] = dist[tx][ty];
        }
    }
}

int dp[15][1<<13];
bool in[15][1<<13];

struct STA{
    int p,s;
    STA(int p = 0,int s = 0):p(p),s(s){}
};

int cnt(int i)
{
    int ret = 0;
    while(i){
        if(i&1)ret++;
        i>>=1;
    }
    return ret;
}

void solve()
{
    xx[0] = x1;yy[0] = y1;
    xx[1] = x2;yy[1] = y2;
    tot = 2;
    id[x1][y1] = 0;id[x2][y2] = 1;
    for(int i = 0; i<n;++i){
        for(int j = 0;j<n;++j){
            if(g[i][j] == '$'){
                id[i][j] = tot;
                xx[tot] = i;
                yy[tot] = j;
                if(i == x1&&j == y1)dis[0][tot] = dis[tot][0] = 0;
                else if(i == x2 &&j == y2)dis[1][tot] = dis[tot][1] = 0;
                tot ++;
            }
        }
    }
    for(int i = 0; i<tot;++i){
        bfs(i,Pos(xx[i],yy[i]));
    }
    memset(dp,-1,sizeof(dp));
    dp[0][0] = 0;
    memset(in,0,sizeof(in));
    queue<STA> q;
    q.push(STA(0,0));
    in[0][0] = 1;
    while(!q.empty()){
        STA st = q.front();q.pop();
        int s = st.s;
        in[st.p][st.s] = 0;
        for(int i = 0;i<tot;++i){
            if(dis[st.p][i] == -1)continue;
            int cost = dis[st.p][i];
            if(dp[i][s|(1<<i)] == -1 || dp[i][s|(1<<i)]>dp[st.p][s]+cost){
                dp[i][s|(1<<i)] = dp[st.p][s]+cost;
                if(!in[i][s|(1<<i)]){
                    q.push(STA(i,s|(1<<i)));
                    in[i][s|(1<<i)] = 1;
                }
            }
        }
    }
    int maxn = -1;
    int ans = -1;
    for(int i = 0 ;i < (1<<tot);++i){
        if(dp[1][i] == -1)continue;
        int c = cnt(i);
        if(c>maxn|| ans == -1 || (c == maxn&&dp[1][i]<ans)){
            maxn = c;
            ans = dp[1][i];
        }
    }
    if(ans == -1) {
        puts("-1");
        return;
    }
    ans += (maxn-2) *2;
    printf("%d\n",ans);
}

int main()
{
//    freopen("data.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(dis,-1,sizeof(dis));
        memset(id,-1,sizeof(id));
        for(int i = 0; i < n; ++i){
            scanf("%s",g[i]);
        }
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        x1--;y1--;x2--;y2--;
        solve();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章