[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 }
View Code

 

posted @ 2015-06-24 22:40  TonyFang  阅读(203)  评论(0编辑  收藏  举报