UVA 662 Fast Food

来源:互联网 发布:基于栈的列表 java 编辑:程序博客网 时间:2024/05/22 16:50

大意略。

有些地方参考了别人的博客。

思路:区间DP,一开始根本就没有思路,想了很久,很多方面木有想清楚啊,后来发现DP方程可以这样表示:

dis[i][j]可以表示在餐馆i~j建立仓库的最小距离,最小距离便是在(i+j)/2建立餐馆,这个可以证明的。

d[i][j] = min(d[i][j], d[i-1][k] + dis[k+1][j]);

d[i][j]表示从前j个餐馆内建立i个仓库,d[i-1][k] + dis[k+1][j]表示的是在1~k内范围建有i-1个仓库,而k+1~j的餐馆是由第i个仓库来管理的,于是也变成了在那个最优位置选餐馆的问题了,k的范围(1<=k < j)。

由于题目有序,可以用递归的方式输出路径。

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <string>#include <cmath>using namespace std;const int MAXN = 210;const int INF = 0x3f3f3f3f;int N, K;int dis[MAXN][MAXN];int d[MAXN][MAXN];int A[MAXN];int fa[MAXN][MAXN];void init(){memset(dis, 0, sizeof(dis));memset(d, INF, sizeof(d));memset(fa, 0, sizeof(fa));}int read_case(){init();scanf("%d%d", &N, &K);if(!N && !K) return 0;for(int i = 1; i <= N; i++) scanf("%d", &A[i]);for(int i = 1; i <= N; i++){for(int j = 1; j <= N; j++){for(int k = i; k <= j; k++){dis[i][j] += abs(A[k] - A[(i+j)/2]);}}}return 1;}int dp(){for(int i = 1; i <= N; i++) d[1][i] = dis[1][i];for(int i = 2; i <= K; i++){for(int j = 1; j <= N; j++){for(int k = 1; k < j; k++){if(d[i][j] > d[i-1][k] + dis[k+1][j]){d[i][j] = d[i-1][k] + dis[k+1][j];fa[i][j] = k;}}}}return d[K][N];}void print_ans(int i, int j){int t = fa[i][j];if(t != 1) print_ans(i, t);printf("Depot %d at restaurant %d serves restaurants %d to %d\n", i, (t+1+j)/2, t+1, j);}void solve(){int ans = dp();print_ans(K, N);printf("Total distance sum = %d\n", ans);}int main(){int times = 0;while(read_case()){printf("Chain %d\n", ++times);solve();printf("\n");}return 0;}

原创粉丝点击