您的位置:首页 > 其它

Sicily 1828 Minimal(动态规划)

2010-09-29 01:14 435 查看
//动态规划
//这题的关键在于先排序,只有先排序,后面动规的思路才能出来,我就是想不到得先排序,卡了好久还得别人提醒
//我是NC不解释
//题意是对2个集合寻找N对数对,使得数对的距离之和最小
//如果你先排好序,那么用DP(i,j)表示A集合的前i个点与B集合前j个点的最优值
//那么对于第i+1个A集合的点而言,他的最优解就是前i个点与B集合前j个点的最优值加上第i+1个点与第j+1个点的距离
//或许i+1与j+1配对不是最好的,它可能比上一个状态DP(i+1,j)要差
//综上
//动态转移方程就是
//dp(i,j) = min(dp(i-1,j-1) + dis(i,j),dp(i,j-1));
//当然这题的边界处理也比较重要
//最初的状态自然是对排序后的点按集合下表按顺序配对
//1-1,2-2,3-3......n-n,X-n+1...X-m;详细的处理可见代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int A[505],B[505],N,M;
int dp[505][505],dis[505][505];
int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
memset(dp,0,sizeof(dp));
for(int i = 1;i <= N;++i)
scanf("%d",&A[i]);
for(int j = 1;j <= M;++j)
scanf("%d",&B[j]);
sort(A+1,A+N+1);
sort(B+1,B+M+1);
for(int i = 1;i <= N;++i)
for(int j = 1;j <= M;++j)
dis[i][j] = abs(A[i] - B[j]);
for(int i = 1;i <= N;++i)
{
if(i == 1)	dp[i][i] = dis[1][1];
else dp[i][i] = dp[i-1][i-1] + dis[i][i];//初始化边界
}
for(int i = 1;i <= N;++i)
for(int j = i+1;j <= M;++j)
dp[i][j] = min(dp[i-1][j-1] + dis[i][j],dp[i][j-1]);//状态转移
printf("%d/n",dp
[M]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: