题意:你是一个老板,在一条高速路上有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; }