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;
}

猜你喜欢

转载自www.cnblogs.com/shuiyonglewodezzzzz/p/11538191.html