zoukankan      html  css  js  c++  java
  • CODEVS_2800 送外卖 状态压缩+动态规划

    原题链接:http://codevs.cn/problem/2800/

    题目描述 Description

    有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。

    输入描述 Input Description

    第一行一个正整数n (1<=n<=15)

    接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。

    输出描述 Output Description

    一个正整数表示最少花费的时间

    样例输入 Sample Input
    3
    0 1 10 10
    1 0 1 2
    10 1 0 10
    10 2 10 0
    样例输出 Sample Output

    8

    数据范围及提示 Data Size & Hint

    1<=n<=15

    这道题很容易想到状压dp,首先跑一遍floyd求出各个点之间的最短路,然后dp。

    状态是dp[i][j]表示状态为i(二进制,表示是否访问过每个点),在位置j时的最短路。

    转移就是:dp[i][j]=min(dp[i-(1<<v)][u]+grid[u][v],dp[i][j]),其中v是当前位置,u是上一个状态的位置。

    需要注意的是dp的顺序应该是由含1的个数少的二进制到1的个数高的二进制;由于最开始就在0位置,所以dp[(1<<n)-1][0]不可能被转移到,所以最后的答案应该是ans=min(ans,dp[(1<<n)-1][i]+grid[i][0]),其中0<=i<n。

    详见代码:

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #include<climits>
    #define INF INT_MAX
    #define MAX_S 1<<16
    #define MAX_N 17
    using namespace std;
    
    struct node
    {
        int val,num;
        node(int v,int n)
            {val=v;num=n;}
        node(){}
    };
    
    node one[MAX_S];
    int grid[MAX_N][MAX_N];
    int n;
    int dp[MAX_S][MAX_N];
    int numOfOne(int x)
    {
        int res=0;
        for(int i=0;i<n;i++)
            if((x>>i)&1)res++;
        return res;
    }
    
    void floyd()
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int k=0;k<n;k++)
                    grid[i][j]=min(grid[i][j],grid[i][k]+grid[k][j]);
    }
    
    bool cmp(node a,node b)
    {
        return a.num<b.num;
    }
    
    int main()
    {
        scanf("%d",&n);
        n++;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&grid[i][j]);
        int totS=1<<n;
        for(int i=0;i<totS;i++)one[i]=node(i,numOfOne(i));
    
        for(int i=0;i<totS;i++)
            for(int j=0;j<n;j++)
                dp[i][j]=INF;
    
        floyd();
        sort(one,one+totS,cmp);
        dp[1][0]=0;
        for(int i=0;i<totS;i++)
        {
            int s=one[i].val;
            for(int v=0;v<n;v++)
            {
                if(!((s>>v)&1))continue;
                int t=s-(1<<v);
                int tmp=INF;
                for(int u=0;u<n;u++)
                {
                    if((!((t>>u)&1))||dp[t][u]==INF)continue;
                    tmp=min(tmp,dp[t][u]+grid[u][v]);
                }
                if(tmp!=INF)
                    dp[s][v]=tmp;
            }
        }
        int ans=INF;
        for(int i=0;i<n;i++)
            ans=dp[totS-1][i]==INF?ans:min(ans,dp[totS-1][i]+grid[i][0]);
        cout<<ans<<endl;
        return 0;
    }
    


  • 相关阅读:
    TypeScript学习笔记(七):模块
    TypeScript学习笔记(六):泛型
    TypeScript学习笔记(五):接口
    TypeScript学习笔记(四):函数
    TypeScript学习笔记(三):类
    TypeScript学习笔记(二):基本数据类型及数据转换
    TypeScript学习笔记(一):介绍及环境搭建
    Egret的VS环境搭配
    [U3D Demo] 手机飞机大战
    Unity3D之UGUI学习笔记(三):EventSystem
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4524040.html
Copyright © 2011-2022 走看看