zoukankan      html  css  js  c++  java
  • COJ 1175 A Tour Around Hangzhou (最短路+状态压缩DP)

    模型:给一个n个点的无向带权图,求从指定起点出发,经过指定的k个点(顺序不定)最后回到起点的最小代价。

    数据范围:n<=10^4, m<=10^5, k<15

    分析:先求最短路,求出从指定的k+1(含起点)个点到其他点的最小代价,然后建立k+1个点之间的最小代价邻接矩阵。最后用状态压缩DP求结果(状态压缩DP参考上一篇)。

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    #define MIN(a,b) ((a)<(b)?(a):(b))
    #define INF 0x3f3f3f3f
    #define N 10010
    #define M 200010
    #define K 15
    int n,m,k,e;
    int first[N],next[M],v[M],w[M];
    int id[K];
    int d[K][N];
    bool inq[N];
    
    int g[K][K];
    int dp[1<<K][K];
    
    void init()
    {
        e=0;
        memset(first,-1,sizeof(first));
    }
    void add(int a,int b,int c)
    {
        v[e]=b;
        w[e]=c;
        next[e]=first[a];
        first[a]=e++;
    }
    void spfa(int i)
    {
        int a,b,j;
        a=id[i];
        queue<int>q;
    
        memset(inq,0,sizeof(inq));
        memset(d[i],0x3f,sizeof(d[i]));
        d[i][a]=0;
    
        q.push(a);
        inq[a]=1;
    
        while(!q.empty())
        {
            a=q.front(),q.pop();
            inq[a]=0;
    
            for(j=first[a];j!=-1;j=next[j])
            {
                b=v[j];
                if(d[i][b]>d[i][a]+w[j])
                {
                    d[i][b]=d[i][a]+w[j];
                    if(!inq[b]) inq[b]=1,q.push(b);
                }
            }
        }
    }
    int DP(int s,int last)
    {
        if(dp[s][last]!=-1) return dp[s][last];
    
        int ns=s^(1<<last);
        if(ns==1)   return g[0][last];
    
        int ret=INF;
        for(int i=1;i<k;i++)    if((ns>>i)&1)
        {
            ret=MIN(ret,DP(ns,i)+g[i][last]);
        }
        return dp[s][last]=ret;
    }
    int main()
    {
        int i,j,a,b,c;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            init();
            while(m--)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            k++;
            for(i=0;i<k;i++)
            {
                scanf("%d",&id[i]);
                spfa(i);
            }
            for(i=0;i<k;i++)
            {
                for(j=0;j<k;j++)
                {
                    g[i][j]=d[i][id[j]];
                }
            }
            int ans=INF;
            memset(dp,-1,sizeof(dp));
            for(i=0;i<k;i++)
            {
                ans=MIN(ans,DP((1<<k)-1,i)+g[0][i]);
            }
            if(ans<INF) printf("%d\n",ans);
            else    puts("What a pity");
        }
        return 0;
    }
  • 相关阅读:
    2021.01.28 Rating赛 解题/补题报告
    2021.01.23 Rating赛 补题&解题报告
    ACM 实验室2020.11.08天梯赛练习*5
    6. Python 基础 dict 字典 查找方法 set() 集合 公共方法
    5. python 基础 list [] 列表 tuple () 元组
    4. python 操作字符串 字符串的一些方法
    3. python基础 转化字符类型 循环
    2. python 数据类型 格式化
    1. Python是编译性语言解释性语言 pyCharm 配置
    科二 教育教学知识与能力4
  • 原文地址:https://www.cnblogs.com/algorithms/p/2623639.html
Copyright © 2011-2022 走看看