• HDU_3681 TSP问题,状压DP


    <p>吐槽一下,最近事情真是多。。。大创+大挑+考试+实验报告(一个礼拜5个实验。。。)+各种抄作业+帮四省赛装电脑,然后一直没怎么做题。。。</p><p>然后再吐槽一下这道题,读题不细心真是惨啊。。。一开始看成了G点和Y点分别不超过15个,想想,加起来用30个点,我去。。。这怎么搞。。。拼命搞了两天没搞出来。。。两天以后又看了一下题目,发现是一共加起来不超过15个点(醉了,难怪我英语可能要挂科了),这就是一个普通的TSP问题了,不过并不是遍历所有的点一次,而是选定的点各一次,这个时候加一个末状态就好了。先建图,每个点做一次bfs就好了(找出最短路径),dp[s][i]表示第s状态最后到达i点的最大剩余体力。转移方程就是dp[s][j] = max(dp[pre_s][i]-dis[i][j]),这里要注意一下边界问题。。。对于TSP问题,我总觉的我的写法比较奇葩(但是都过了,以后如果出问题了再改吧)。最近感觉c++迭代器里面的东西确实好用。。。</p><p>下面直接给代码</p>
    
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #define ll  long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    
    using namespace std;
    
    typedef pair<int,int>   pii;
    
    pii no[16];
    int en,st,dis[16][16][16][16],n,N,M,dp[1<<16][16];
    char mat[17][17];
    int dx[4] = {-1,1,0,0},dy[4] = {0,0,-1,1};
    void input(){
        n = 0;
        en = 0;
        FOR(i,0,N){
            scanf("%s",mat[i]);
            FOR(j,0,M){
                if(mat[i][j] == 'F'){
                    st = n;
                    en = en | (1<<n);
                    no[n++] = make_pair(i,j);
                    continue;
                }
                if(mat[i][j] == 'G'){
                    no[n++] = make_pair(i,j);
                    continue;
                }
                if(mat[i][j] == 'Y'){
                    en = en | (1<<n);
                    no[n++] = make_pair(i,j);
                    continue;
                }
            }
        }
    }
    
    void bfs(pii um){
        queue <pii> q;
        dis[um.first][um.second][um.first][um.second] = 0;
        q.push(um);
        while(!q.empty()){
            pii u = q.front();  q.pop();
            int x = u.first,y = u.second;
            FOR(i,0,4){
                int nx = x + dx[i],ny = y + dy[i];
                if(nx < 0 || nx >= N || ny < 0 || ny >= M)   continue;
                if(mat[nx][ny] == 'D')  continue;
                if(dis[um.first][um.second][nx][ny] != -1)    continue;
                dis[um.first][um.second][nx][ny] = dis[um.first][um.second][x][y] + 1;
                q.push(make_pair(nx,ny));
            }
        }
    }
    
    bool init(){
        memset(dis,-1,sizeof(dis));
        FOR(i,0,n){
            bfs(no[i]);
        }
        FOR(i,0,n){
            if(mat[no[i].first][no[i].second] != 'G' && dis[no[st].first][no[st].second][no[i].first][no[i].second] == -1)
                return false;
        }
        return true;
    }
    
    bool check(int p){
        FOR(s,0,1<<n){
            FOR(i,0,n)
                dp[s][i] = -1;
        }
        dp[1<<st][st] = p;
        FOR(s,0,1<<n){
            if((s & (1<<st)) == 0)    continue;
            FOR(j,0,n){
                if((s & (1<<j)) == 0)   continue;
                if(j == st) continue;
                int pre_s = s ^ (1<<j);
                FOR(i,0,n){
                    if((pre_s & (1<<i)) == 0) continue;
                    int tem = dis[no[i].first][no[i].second][no[j].first][no[j].second];
                    if(tem == -1)   continue;
                    dp[s][j] = max(dp[pre_s][i]-tem,dp[s][j]);
                }
                if(dp[s][j] == -1)  continue;
                if((s & en) == en && dp[s][j] != -1)    return true;
                if(mat[no[j].first][no[j].second] == 'G')   dp[s][j] = p;
            }
        }
        return false;
    }
    
    int solve(){
        int l = 0,r = 1111111;
        check(2);
        while(l < r){
            int mid = (l+r)>>1;
            if(!check(mid)) l = mid+1;
            else r = mid;
        }
        return l;
    }
    
    int main(){
        //freopen("test.in","r",stdin);
        while(scanf("%d%d",&N,&M),(N || M)){
            input();
            if(en == (1<<st))   printf("0
    ");
            else if(!init())    printf("-1
    ");
            else    printf("%d
    ",solve());
        }
        return 0;
    }
    



  • 相关阅读:
    Recommended Books for Algo Trading in 2020
    Market Making is simpler than you think!
    Top Crypto Market Makers of 2020
    Top Crypto Market Makers, Rated and Reviewed
    爬取伯乐在线文章(五)itemloader
    爬取伯乐在线文章(四)将爬取结果保存到MySQL
    爬取伯乐在线文章(三)爬取所有页面的文章
    爬取伯乐在线文章(二)通过xpath提取源文件中需要的内容
    爬取伯乐在线文章(一)
    爬虫去重策略
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4555868.html
Copyright © 2020-2023  润新知