uva662(DP)

来源:互联网 发布:java 生产表单创建表 编辑:程序博客网 时间:2024/06/14 22:38

题目大意:
给出n和k,分别表示在n个餐馆需要建立k个仓库,需要求出最小代价,代价就是n个餐馆到离它最近的仓库的距离的和。

思路:
dp[i][j]表示在前j个餐馆建立了i个仓库。
cost[i][j]表示从i到j建立一个仓库,需要花费的最小的代价。(那么肯定是建在中位数的位置)
那么dp[i][j] = min(dp[i][j],dp[i - 1][k] + cost[k + 1][j]);
最后打印出来就可以了。
代码:

#include <iostream>using namespace std;#include <cstring>#include <stdio.h>#include <cmath>const int INF = 0x3f3f3f3f;int dis[205];int cost[205][205];int dp[35][205];int father[35][205];void print(int k,int n) {    if(k)  {        int t = father[k][n] + 1,mid = (t + n)/2;        print(k - 1,father[k][n]);        if(t == n)            printf("Depot %d at restaurant %d serves restaurant %d\n",k,mid,n);        else            printf("Depot %d at restaurant %d serves restaurants %d to %d\n",k,mid,t,n);    }}int main() {    int T = 0;    int k,n;    while(scanf("%d %d",&n,&k) && n) {        for(int i = 1; i <= n; i++) {            scanf("%d",&dis[i]);        }        memset(father,0,sizeof(father));        memset(cost,0,sizeof(cost));        for(int i = 1; i <= n; i++) {            for(int j = i; j <= n; j++) {                //cost[i][j] = 0;                int mid = (i  + j) /2;                for(int q = i; q <= j; q++)                    cost[i][j] += (abs(dis[q] - dis[mid]));            }        }        for(int i = 1; i <= n; i++)            dp[1][i] = cost[1][i];        for(int i = 2; i <= k; i++) {            for(int j = i; j <= n; j++) {                dp[i][j] = 0xffffff;                for(int q = i - 1; q < j; q++)                    if(dp[i][j] > dp[i - 1][q] + cost[q + 1][j]) {                        dp[i][j] = dp[i - 1][q] + cost[q + 1][j];                        father[i][j] = q;                     }            }        }        printf("Chain %d\n",++T);        print(k,n);        printf("Total distance sum = %d\n\n",dp[k][n]);    }    return 0;}
0 0
原创粉丝点击