zoukankan      html  css  js  c++  java
  • hdu 4284 Travel 夜

    http://acm.hdu.edu.cn/showproblem.php?pid=4284

    这题后台数据相当强呀 

    思路:先用flody  求得任意两点间的最短距离

    然后再用 状态压缩+DP

    dist [ i ] [ j ]  表示已经到 i 状态压缩表示的城市 拿到证件 打工 而且现在在 第 j 个要去的城市  这种情况下剩余的最多钱

    不断更新  最后看是否有满足条件 去过所以要去的城市 而且还能回到原点的  状态

    代码及其注释:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    
    #define LL long long
    
    using namespace std;
    
    const int N=103;
    const int H=16;
    const int INF=0x0fffffff;
    int dist[1<<16][H];//此状态剩余最多钱
    int d[N][N];//最短路
    struct node
    {
        int k,c,d;
    }mem[H];//要去的城市相关信息
    bool cmp(node x,node y)//按城市序号排序 主要是让原点 在 0 位置
    {
        return x.k<y.k;
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m,money,h,K;;
            scanf("%d %d %d",&n,&m,&money);
            for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            {
                if(i==j)d[i][j]=0;
                else d[i][j]=INF;//初始化
            }
            while(m--)
            {
                int i,j,p;
                scanf("%d %d %d",&i,&j,&p);
                d[i][j]=d[j][i]=min(d[i][j],p);
            }
            scanf("%d",&h);
            int have1=false;
            for(int i=0;i<h;++i)
            {
                scanf("%d %d %d",&mem[i].k,&mem[i].c,&mem[i].d);
                if(mem[i].k==1)
                have1=true;
            }
            if(!have1)//如果原点不在则将原点加入  这样不会影响最终结果 而且便于运算
            {
                mem[h].c=mem[h].d=0;
                mem[h].k=1;++h;
            }
            sort(mem,mem+h,cmp);
            for(int l=1;l<=n;++l)
            for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            if(d[i][j]>d[i][l]+d[l][j])
            d[i][j]=d[i][l]+d[l][j];//求最短路
            memset(dist,-1,sizeof(dist));
            K=(1<<h)-1;
            dist[0][0]=money;//在没有去过任何城市时 在第0个要去的城市(原点)时所有钱
            for(int i=0;i<K;++i)
            {
                for(int j=0;j<h;++j)//i 和 j表示的顺序不能变 因为更新时是想i 变大的方向更新
                {
                    if(dist[i][j]==-1)
                    continue;
                    for(int l=0;l<h;++l)
                    {
                        int temp=i|(1<<l);
                        if(temp==i)//已经去过 拿证件 打工
                        continue;
                        int more=dist[i][j]-d[mem[j].k][mem[l].k]-mem[l].d;//看是否可以成功到达 并且拿到证件
                        if(more<0)
                        continue ;
                        dist[temp][l]=max(dist[temp][l],more+mem[l].c);//更新
                    }
                }
            }
            bool ans=false;
            for(int i=0;i<h;++i)
            if(dist[K][i]>=d[mem[i].k][mem[0].k])//去过所有要去的城市 而且能回到原点
            {ans=true;break;}
            if(ans)
            printf("YES\n");
            else
            printf("NO\n");
        }
        return 0;
    }
    
  • 相关阅读:
    20个设计精致的用户界面 PSD 源文件免费下载
    Mergely – 免费的在线文档对比和合并工具
    你应该知道的10个奇特的 HTML5 单页网站
    One Page Scroll – 实现苹果风格的单页滚动效果
    学习如何制作 404 错误页面的15个最佳案例
    Rainyday.js – 傻眼了!竟然有如此逼真的雨滴效果
    Lo-Dash – 替代 Underscore 的优秀 JS 工具库
    30个实用的 Photoshop 动作《免费下载》
    Wrangle – 响应式的,触摸友好的多选插件
    经典案例:那些让人赞不绝口的创新 HTML5 网站
  • 原文地址:https://www.cnblogs.com/liulangye/p/2685211.html
Copyright © 2011-2022 走看看