首页 > 代码库 > POJ 2137 Cowties 线性DP

POJ 2137 Cowties 线性DP

题意:n只牛,第i只牛有Si个合法的坐标(x,y),当n只牛都在它合法的坐标上时,花费为相邻两个点的距离和的累加和(1->2,..n->1).n<=100,si<=40,问最小的花费?

第i只牛,有num[i]种决策

设dp[i][p][j] 前i个人,第1个人在p 最后一个人在j(不连成环)的最小花费
最后ans连成环时需要第一个人的状态.(或者枚举起点)
按照最后一个人已经前一个人的位置转移状态即可 O(100*40*40*40=6e6)

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<double,double> ii; 
const int N=2e2+20;
const double inf=2e8;
//题意:n只牛,第i只牛有Si个合法的坐标(x,y),当n只牛都在它合法的坐标上时,
//花费为相邻两个点的距离和的累加和(1->2,..n->1).问最小的花费?
double dp[N][60][60];
int n,num[N];
struct node{
	double x,y;
}a[N][N];
double dis(int i,int p,int j,int k)
{
	return sqrt((a[i][j].x-a[p][k].x)*(a[i][j].x-a[p][k].x)+(a[i][j].y-a[p][k].y)*(a[i][j].y-a[p][k].y));
}
int main()
{
	while(cin>>n)
	{
		int k;
		for(int i=1;i<=n;i++)
		{
			cin>>num[i];
			for(int j=1;j<=num[i];j++)
				cin>>a[i][j].x>>a[i][j].y;
		}
		for(int i=0;i<=n;i++)
			for(int j=0;j<=60;j++)
				for(int k=0;k<=60;k++)
					dp[i][j][k]=inf;
		for(int i=1;i<=num[1];i++)
			dp[1][i][i]=0;
		//第i个人有num[i]种决策 
		double ans=2e8;
		for(int i=2;i<=n;i++)
		{
			for(int p=1;p<=num[1];p++)
			{
				for(int j=1;j<=num[i];j++)
				{
					for(int k=1;k<=num[i-1];k++)//枚举前一个人 
					{
						dp[i][p][j]=min(dp[i][p][j],dp[i-1][p][k]+dis(i,i-1,j,k));
					//	printf("%lf ",dp[i][p][j]);
					}
				//	printf("\n");
				}
			}
		}
		for(int i=1;i<=num[1];i++)
		{
			for(int j=1;j<=num[n];j++)
			{
				ans=min(ans,dp[n][i][j]+dis(1,n,i,j));
			}
		}
		ans*=100;
		int res=(int)ans;
		printf("%d\n",res);
	}
	return 0;
}

  

POJ 2137 Cowties 线性DP