zoukankan      html  css  js  c++  java
  • hdu 4284 Travel(floyd + TSP)

    虽然题中有n<=100个点,但实际上你必须走过的点只有H<=15个。而且经过任意点但不消耗C[i]跟D[i]可以为无限次,所以可以floyd预处理出H个点的最短路,之后剩下的。。。就成了裸的TSP了,dp[sta][i]表示已经遍历过了sta集合中的点,现在在i点所需的最少花费。dp[i][j]=-1表示该点不可到达。。但是在最后统计最小解的时候要特判。。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<fstream>
    #include<sstream>
    #include<bitset>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FF(i, a, b) for(int i=a; i<b; i++)
    #define FD(i, a, b) for(int i=a; i>=b; i--)
    #define REP(i, n) for(int i=0; i<n; i++)
    #define CLR(a, b) memset(a, b, sizeof(a))
    #define debug puts("**debug**")
    #define LL long long
    #define PB push_back
    #define MP make_pair
    #define eps 1e-10
    using namespace std;
    
    const int maxn = 105;
    const int INF = 1e9;
    int n, m, H, V, T;
    int go[20], C[20], D[20], g[maxn][maxn], dp[1<<15][20];
    
    void floyd()
    {
        FF(i, 1, n+1)
        {
            FF(j, 1, n+1) g[i][j] = INF;
            g[i][i] = 0;
        }
        int u, v, w;
        while(m--)
        {
            scanf("%d%d%d", &u, &v, &w);
            if(g[u][v] > w) g[u][v] = g[v][u] = w;
        }
        FF(k, 1, n+1) FF(i, 1, n+1) FF(j, 1, n+1) g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    }
    
    int main()
    {
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d%d", &n, &m, &V);
            floyd();
    
            scanf("%d", &H);
            REP(i, H) scanf("%d%d%d", &go[i], &C[i], &D[i]);
    
            int tot = (1<<H) - 1;
            CLR(dp, -1);
            REP(i, H) if(V - g[1][go[i]] >= D[i]) dp[1<<i][i] = g[1][go[i]] - C[i] + D[i];
    
            FF(i, 1, tot+1) REP(j, H) if(dp[i][j] != -1) //dp[i][j]可到达
            {
                REP(k, H) if((i&(1<<k)) == 0) //k点未到达
                {
                    int sta = i|(1<<k);
                    if(V - dp[i][j] - g[go[j]][go[k]] >= D[k])
                    {
                        if(dp[sta][k] == -1) dp[sta][k] = dp[i][j] + g[go[j]][go[k]] - C[k] + D[k];
                        else dp[sta][k] = min(dp[sta][k], dp[i][j] + g[go[j]][go[k]] - C[k] + D[k]);
                    }
                }
            }
            int ans = INF;
            //特判dp[tot][i]可到达,最开始忘了。。。10+wa
            REP(i, H) if(dp[tot][i] != -1) ans = min(ans, dp[tot][i] + g[go[i]][1]);
            printf("%s
    ", ans <= V ? "YES" : "NO");
        }
        return 0;
    }
    


  • 相关阅读:
    vue element-ui配置第三方图标库
    HTTP协议:状态码
    HTTP协议:无状态
    CDN:基础知识
    【转载】浅析机器视觉中的照明系统(该如何打光)
    nginx 端口转发
    Gitlab 备份 | 恢复 | 卸载 | 迁移 | 版本升级
    微信小程序支付服务端.net core实现,简单直接
    生产级gitlab备份
    背锅之旅:前任对我的爱-只备份不删除导致的磁盘爆满
  • 原文地址:https://www.cnblogs.com/riskyer/p/3310736.html
Copyright © 2011-2022 走看看