zoukankan      html  css  js  c++  java
  • 旅游景点 Tourist Attractions【状压dp】

    旅游景点 Tourist Attractions【状压dp】

    题目链接:https://www.luogu.com.cn/problem/P3451

    大意:给出n个城市和城市间的道路,给定一个k,从1开始走,必须经过2-k+1的所有城市,问最小路程。

    Sample input

    8 15 4
    1 2 3
    1 3 4
    1 4 4
    1 6 2
    1 7 3
    2 3 6
    2 4 2
    2 5 2
    3 4 3
    3 6 3
    3 8 6
    4 5 2
    4 8 6
    5 7 4
    5 8 6
    3
    2 3
    3 4
    3 5
    

    Sample output

    19
    

    思路

    每个城市只有到过和没到过两种情况,很自然的想到状压dp

    用dijkstra求出1-k+1每个点的单源最短路 (我一开用的floyd貌似会炸,也可能我写的不对)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define pa pair<int, int>//用这个pair相当于省略了一个node结构体
    using namespace std;
    const int maxn = 20010, inf = 0x3f3f3f3f;
    int n, m, K, len, ed, a[25], dis[25][25], d[maxn], head[maxn],dp[1<<20][25], u, v, w, q;
    bool vis[maxn];
    struct edge{//边结构体
        int to, nx, dis;
    }e[400005];
    void insert(int u, int v, int w){//插入边
        e[++len].to = v;
        e[len].dis = w;
        e[len].nx = head[u];
        head[u] = len;
    }
    void dijs(int x){//求最短路,标准dijkstra,不多说
        priority_queue<pa, vector<pa>, greater<pa> > q; //定义pair的小根堆
        for(int i=1; i<=n; i++) d[i] = inf, vis[i] = 0;//初始化d[],d[i]表示当前点到i的最短距离
        d[x] = 0;
        q.push(make_pair(0, x));
        while(!q.empty()){
            int now = q.top().second;
            q.pop();
            if(vis[now]) continue;
            vis[now] = 1;
            for(int i=head[now]; i; i=e[i].nx){
                if(d[now]+e[i].dis<d[e[i].to]){
    				d[e[i].to]=d[now]+e[i].dis;
    				q.push(make_pair(d[e[i].to],e[i].to));
    			}
            }
        }
        for(int i=1; i<=K+1; i++) dis[x][i] = d[i];
        dis[x][0] = d[n];//一个小技巧,用0的位置存n,我们不必把dis开到n*n
    }
    void sol(){//状压dp
        for(int now=0; now<=ed; now++)//枚举当前状态
            for(int x=1; x<=K+1; x++)//枚举当前状态下最后到达的城市
                if(dp[now][x] != -1)//保证x是能到达的
                    for(int i=2; i<=K+1; i++){//枚举中转城市
                        int to = (now | (1<<(i-2)));//到达中转城市后的状态
                        if((now & a[i]) == a[i])//满足限制条件
                            if(dp[to][i] > dp[now][x] + dis[x][i] || dp[to][i] == -1)
                                dp[to][i] = dp[now][x] + dis[x][i];
                    }
    }
    int main(){
        scanf("%d%d%d", &n, &m, &K);
        ed = (1<<K) - 1;//最大状态
        for(int i=1; i<=m; i++){
            scanf("%d%d%d", &u, &v, &w);
            insert(u, v, w); insert(v, u, w);
        }
        for(int i=1; i<=K+1; i++) dijs(i);
        scanf("%d", &q);
        while(q--){
            scanf("%d%d", &u, &v);
            a[v] += 1<<(u-2);
        }
        memset(dp, -1, sizeof(dp));
        dp[0][1] = 0;
        sol();
        int ans = inf;
        for(int i=1; i<=K+1; i++)
            if(dp[ed][i] != -1) ans = min(ans, dp[ed][i]+dis[i][0]);
        printf("%d
    ", ans);
        return 0;   
    }
    
  • 相关阅读:
    误删除pycharm项目中的文件,如何恢复?
    Python/PHP 远程文件/图片 下载
    Python 字节与字符串的转换
    Python中的Json模块dumps、loads、dump、load函数介绍
    Python 连接数据库失败
    Python 模块搜索路径
    Python 操作 PostgreSQL 数据库
    从shell(终端)中退出python
    URL 传参中需要处理的特殊字符
    PHP 命名空间和自动加载
  • 原文地址:https://www.cnblogs.com/hzoi-poozhai/p/12748020.html
Copyright © 2011-2022 走看看