zoukankan      html  css  js  c++  java
  • HDU4281:Judges' response (mTSP问题)(01背包 状态压缩 DP)

    题意:输入n,m,表示有n个地点,m为最大的花费。接着输入n个地点的坐标x,y,起点为第一个地点。还有n个地点的花费。第一问求,每个人有m个钱,求访问完n个点至少需要多少个人。  第二问是可以有任意多个人,求从起点出发遍历n个点后再回到起点的最少距离。

    分析:第一问可以状态压缩后,进行01背包。第二问先找到一个人遍历(1~n)个点再回到起点的位置的最短距离,然后把一个人到达n个点的距离进行分解。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include<cmath>
    
    using namespace std;
    
    const int maxn = 20;
    const int oo = 1<<30;
    
    int x[maxn], y[maxn], c[maxn];
    int ok[1<<17], dis[20][20];
    int best[1<<17], tem[20][1<<17];
    int sta[1<<17], len;
    
    void Init(int n)
    {
        int End = (1<<n);
        for(int i = 0; i<End; i++)
            best[i] = oo;
        for(int i = 0; i<n; i++)
        {
            for(int j = 0; j<End; j++)
                tem[i][j] = oo;
        }
        tem[0][1] = 0;
    }
    
    int Judge(int state, int n, int m)
    {
        int sum = 0;
        for(int i=0; i<n; i++)
            if(state&(1<<i))
                sum+=c[i];
        return sum<=m;
    }
    int cal(int i,int j)
    {
        return ceil(sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
    }
    
    int DP(int n)
    {
        int dp[1<<17];
        fill(dp, dp+(1<<n), oo);
        int state = (1<<n)-1;
        dp[0] = 0;
        for(int i=0; i<len; i++)
        {
            for(int j=state; j>=0; j--)
            {
                if(dp[j]!=oo&&!(sta[i]&j))
                    dp[sta[i]+j]=min(dp[sta[i]+j], dp[j]+1);
    
            }
        }
        return dp[state];
    }
    
    int Tsp(int n)
    {
        int state = (1<<n)-1;
        for(int i=0; i<=state; i++)
        {
            if(ok[i])
            {
                for(int j=0; j<n; j++)
                {
                    if(i&(1<<j))
                    {
                        best[i] = min(best[i], tem[j][i]+dis[j][0]);
                        for(int k=0; k<n; k++)
                        {
                            if(!(1&(1<<k)))
                            {
                                tem[k][i|(1<<k)]=min(tem[k][i|(1<<k)], tem[j][i]+dis[j][k]);
                            }
                        }
                    }
                }
            }
        }
        for(int i=1; i<=state; i++)
        {
            if(i&1)
            {
                for(int j=i&(i-1); j; j=i&(j-1))
                {
                    best[i] = min(best[i], best[(i-j)|1]+best[j]);
                }
            }
        }
        return best[state];
    }
    
    int main()
    {
        int n, m;
        while(~scanf("%d %d", &n, &m))
        {
            for(int i=0; i<n; i++)
                scanf("%d %d", &x[i], &y[i]);
            for(int i=0; i<n; i++)
                scanf("%d", &c[i]);
            len =0;
            for(int s=0; s<(1<<n); s++)
            {
                ok[s] = Judge(s, n, m);
                if(ok[s])
                    sta[len++] = s;
            }
            int ans = DP(n);
            Init(n);
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<n; j++)
                {
                    dis[i][j] = cal(i, j);
                }
            }
            if(ans == oo)
            {
                puts("-1 -1");
                continue;
            }
            printf("%d %d
    ", ans, Tsp(n));
    
        }
    
        return 0;
    }
  • 相关阅读:
    指针和引用作为函数参数传递
    cv::Mat.type()
    Matlab 双目标定工具箱
    invalid conversion from `const void*' to `void*'
    error: 'vector' is not a member of cv
    单例模式与静态成员
    RGBD SLAM V2 +Ubuntu 16.04+ROS KINETIC配置及运行
    EntityFrameworkCore + MySQL 主从复制应用读写分离
    Docker 搭建 MySQL8.0 主从复制环境
    Asp.Net Core 项目中使用 Serilog 输出日志到 Elasticsearch
  • 原文地址:https://www.cnblogs.com/mengzhong/p/5473234.html
Copyright © 2011-2022 走看看