• uva-622-dp


    题意:你是一个老板,在一条高速路上有N个餐馆,现在你准备在这些餐馆内选取K个作为基地给其他餐馆供货,那么,供货的花费和距离相关。花费的计算公式如下。

     问你,选取那些餐馆作为基地,并且给那些餐馆供货,使得总的花费最小

    dp[i][j] = min(dp[i-1][p-1]+vpt)

    dp[i][j]表示前i个供货点给前j个餐馆供货时的最小花费,那么dp[i][j] = min(dp[i-1][p-1] + v[p][j])   j>=i 且 i<=p 且p<=j。

    意思就是前i个供货点给前j个餐馆供货时的最小花费等于前i-1个供货点给p-1个餐馆供货+++下标为p到j个餐馆的花费,取最小值就是

    输入

    6 3
    56
    12
    19
    20
    27
    0 0

    输出

    Chain 1
    Depot 1 at restaurant 2 serves restaurants 1 to 3
    Depot 2 at restaurant 4 serves restaurants 4 to 5
    Depot 3 at restaurant 6 serves restaurant 6
    Total distance sum = 8
    #include <string>
    #include<iostream>
    #include <sstream>
    #include<map>
    #include<memory.h>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<math.h>
    #include<iomanip>
    #include<bitset>
    #include"math.h"
    namespace cc
    {
        using std::cout;
        using std::endl;
        using std::cin;
        using std::map;
        using std::vector;
        using std::string;
        using std::sort;
        using std::priority_queue;
        using std::greater;
        using std::vector;
        using std::swap;
        using std::stack;
        using std::bitset;
        using std::stringstream;
        using std::abs;
    
    
    
        constexpr int N = 210;
        constexpr int K = 35;
        int dp[K][N];
        int dis[N][N];
        int n, k;
        int path[N];
    
    
        int disij(int i,int j,bool print,int kk)
        {
            if (dis[i][j] != -1&& print==false)
                return dis[i][j];
            int val = 0;
            if (i == j)
            {
                if (print)
                cout << "Depot " << kk << " at restaurant " <<
                    i << " serves restaurant " << i  << endl;
                val = 0;
            }
            else if((j-i)%2==0)
            {
                int mid = (j - i) / 2+i;
                int s=mid-1, e=mid+1;
                if(print)
                cout << "Depot " << kk << " at restaurant " <<
                    mid << " serves restaurants " << i << " to " << j << endl;
                while (s >= i && e <= j)
                {
                    val += abs(path[mid]-path[s]);
                    val += abs(path[mid]-path[e]);
                    --s;
                    ++e;
                }
            }
            else
            {
                int mid = (j - i) / 2+1+i;
                int s = mid-1, e = mid;
                while (s >= i && e <= j)
                {
                    val += abs(path[mid] - path[s]);
                    val += abs(path[mid] - path[e]);
                    --s;
                    ++e;
                }
                mid = (j - i) /2+i;
                int val2 = 0;
                 s = mid;
                 e = mid + 1;
                while (s >= i && e <= j)
                {
                    val2 += abs(path[mid] - path[s]);
                    val2 += abs(path[mid] - path[e]);
                    --s;
                    ++e;
                }
                if (val2 <= val)
                {
                    val = val2;
                    if (print)
                    {
                        cout << "Depot " << kk << " at restaurant " <<
                            (j - i) / 2 + i << " serves restaurants " << i << " to " << j << endl;
                    }
                
                }
                else
                {
                    if(print)
                    {
                        cout << "Depot " << kk << " at restaurant " <<
                            (j - i) / 2 + 1 + i << " serves restaurants " << i << " to " << j << endl;
                    }
                }
    
            }
            dis[i][j] = val;
            return val;
        }
    
        void printPath(int k2,int val,int e) 
        {
            if (k2 == 0)
                return;
            for (int index = k2; index <= e; index++)
            {
                int mm = dp[k2 - 1][index - 1] + disij(index, e,false,k2);
                if (mm == val)
                {
                    printPath(k2-1,val-disij(index,e, false, k2),index-1);
                    disij(index, e, true, k2);
                    break;
                }
            }
    
    
        }
    
        void ddp() 
        {
            dp[0][0] = 0;
            for (int i=1;i<=k;i++) 
            {
                for (int j=i;j<=n;j++) 
                {
                    //dij
                    int m = 0x7fffffff;
                    for (int index = i;index<=j; index++) 
                    {
                        int mm = dp[i - 1][index - 1] + disij(index,j,false,-1);
                        if (mm < m)
                            m = mm;
                    }
                    dp[i][j] = m;
                }
            }
            
        }
    
        void init() 
        {
            for (int i = 0; i <= k; i++)
                for (int j = 0; j <= n; j++)
                    dp[i][j] = 0x7fffffff - 10000000;
    
        }
        void solve()
        {
            int t = 1;
            while (cin>>n>>k) 
            {
                if (n == 0 && k == 0)
                    return;
                for (int i = 1; i <= n; i++)
                    cin >> path[i];
                init();
                memset(dis,-1,sizeof(dis));
                ddp();
                cout << "Chain " << t << endl;
                printPath(k, dp[k][n], n);
                cout<<"Total distance sum = " << dp[k][n] << endl<<endl;
                ++t;
            }
             
        }
    
    };
    
    
    int main()
    {
    
    #ifndef ONLINE_JUDGE
        freopen("d://1.text", "r", stdin);
        freopen("d://1.out","w",stdout);
    #endif // !ONLINE_JUDGE
        cc::solve();
    
        return 0;
    }
  • 相关阅读:
    时光卷轴,IT启示录2022年5月刊
    乘风破浪,遇见最美Windows 11之现代Windows桌面应用开发 自定义生成配置文件(Directory.Build.props)来实现灵活切换
    源码解读之RedissonLock.lock()方法 爱我
    最小生成树
    tarjan/2sat
    【java校招你不知道的那些事儿】校招和社招的区别是什么?为什么不参加社招
    SQL in 参数化
    手写事件发布/订阅框架(二)
    JDMatrix
    sql的查询多次in 操作的导致查询数据为空
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/11538191.html
Copyright © 2020-2023  润新知