zoukankan      html  css  js  c++  java
  • 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;
    }
    



  • 相关阅读:
    sax解析xml案例二
    mysql之删除重复数据
    Android之Intent探究
    struts2之Action名称的搜索顺序
    struts2自定义拦截器二——模拟session超时的处理
    struts2之防止表单重复提交
    Android之日期及时间选择对话框
    sax解析xml案例一
    Android之单选按钮对话框
    查询修改nls_database_parameters系统配置
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4555868.html
Copyright © 2011-2022 走看看