[FZYZOJ 1017] liqeuer
P1017 -- liqeuer
时间限制:1000MS
内存限制:65536KB
Description
轰的一声,展现在你眼前的是两堆零件和一条岩浆"河",我们将第一堆零件定义为集合S1,第二堆定义为集合S2。
首先,S1的零件个数少于等于S2的零件个数。我们现在设N为S1的零件个数,从S2中挑选出N个零件,使得两个集合的匹配差最小。这样搭建出来的桥才能顺利通过岩浆"河"。
对于两个集合的匹配差在本题定义作此描述: 定义F(S1,S2)=min(|a1-b1|+|a2-b2|+|a3-b3|+...+|an-bn|){n为S1的元素个数,ai∈S1,bi∈S2},F(S1,S2)即为两个集合的匹配差。
Input Format
第一行一个数testcase,表示测试数据组数(0<=testcase<=5)
每组数据的格式如下:第一行两个数n1,n2(0<=n1<=n2<=500),n1表示第一堆零件的个数,n2表示第二堆零件的个数。
接下来n1行,每行一个数,表示S1的各个元素(不超过10000)。再接下来n2行,每行一个数,表示S2的各个元素(同样不超过10000)。
Output Format
输出testcase行,每行一个数。第i行表示第i组数据的两个集合的匹配差值的最小值。
Sample Input
3 10 10 1 2 3 4 5 6 7 8 9 20 10 11 12 13 14 15 16 17 18 19 4 5 1 2 3 4 5 6 7 8 9 8 12 3 4 6 8 10 16 21 25 29 34 25 12 42 35 62 19 31 49 46 37
Sample Output
82 16 129
Hint
【题解】序列动态规划
f[i][j]表示S1匹配到i,S2匹配到j的最小F值
f[i][j]= (i==j) ? (f[i-1][j-1]+abs(a[i]-b[j])) : (min(f[i][j-1], f[i-1][j-1]+abs(a[i]-b[j])))
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 int n1,n2,f[510][510]; 6 int a[510],b[510]; 7 int abs(int x) {return x>0?x:-x;} 8 int main() { 9 int test; scanf("%d",&test); 10 while(test--) { 11 n1=n2=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(f,0,sizeof(f)); 12 scanf("%d%d",&n1,&n2); 13 for (int i=1;i<=n1;++i) scanf("%d",&a[i]); 14 for (int i=1;i<=n2;++i) scanf("%d",&b[i]); 15 sort(a+1,a+n1+1); sort(b+1,b+n2+1); 16 for (int i=1;i<=n1;++i) 17 for (int j=i;j<=n2-n1+i;++j) 18 if(i==j) f[i][j]=f[i-1][j-1]+abs(a[i]-b[j]); 19 else f[i][j]=min(f[i][j-1],f[i-1][j-1]+abs(a[i]-b[j])); 20 printf("%d\n",f[n1][n2]); 21 } 22 return 0; 23 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net