662 - Fast Food

/*
首先預處理用w[i][j]表示從i到j的最小距離和
用d[i][j]表示用在前i個飯店中選j個倉庫的最小距離和
狀態轉移方程d[i][j]=min(d[k][j-1]+w[k+1][i])  k:1->i-1;
然後遞歸打印路徑,如果用非遞歸的話要記錄一下。 
*/
#include <stdio.h>
#include <string.h>
#define maxn 205
int r[maxn],d[maxn][35],w[maxn][maxn],n,k;
int abs(int a)
{
	if(a<0) return -a;
	else return a;
}
int min(int a,int b)
{
	if(a<b) return a;
	else return b;
}
void dp()
{
	for(int i=0;i<n;i++)
	for(int j=0;j+i<n;j++)
	{
		for(int k=j;k<=i+j;k++)
		w[j][i+j]+=abs(r[k]-r[(i+j+j)/2]);
	}
	for(int i=0;i<n;i++)
	d[i][1]=w[0][i];
	for(int i=2;i<=k;i++)
	{
		for(int j=i-1;j<n;j++)
		{
			for(int k=i-2;k<j;k++)
			d[j][i]=min(d[j][i],d[k][i-1]+w[k+1][j]);
		}
	}
}
void printpath(int a,int b,int sum,int c)
{
	if(c==1)
	{ 
		if(a==b)
		printf("Depot %d at restaurant %d serves restaurant %d\n",c,b+1,b+1);
		else
		printf("Depot %d at restaurant %d serves restaurants %d to %d\n",c,(a+b)/2+1,a+1,b+1);
		return;
	}
	for(int i=a;i<b;i++)
	if(d[i][c-1]+w[i+1][b]==sum)
	{
		printpath(0,i,d[i][c-1],c-1);
		if(i+1==b)
		printf("Depot %d at restaurant %d serves restaurant %d\n",c,b+1,b+1);
		else
		printf("Depot %d at restaurant %d serves restaurants %d to %d\n",c,(i+1+b)/2+1,i+1+1,b+1);
		break;
	}
}
int main()
{
	int t=0;
	while(scanf("%d%d",&n,&k)&&!(n==0&&k==0))
	{
		for(int i=0;i<n;i++)
		scanf("%d",&r[i]);
		memset(d,0x7f,sizeof(d));
		memset(w,0,sizeof(w));
		dp();
		printf("Chain %d\n",++t);
		printpath(0,n-1,d[n-1][k],k);
		printf("Total distance sum = %d\n",d[n-1][k]);
		printf("\n");	
	}
	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章