UVA 10271 - Chopsticks

大意: 

在中国,众通常用一双筷子吃饭。但是L先生与众不同:他用三支筷子吃饭。其中的一支长筷子用来叉取大块的食物,而剩下两支用作普通筷子。两支普通筷子的长度应尽可能的接近,而长的那支只要是三支中最长的就可以了。对于一幅筷子的长度ABCABC),定义函数(AB2为这副筷子的“难用度”。

L先生邀请K个人参加他的生日聚会,并且想将他用筷子的方法介绍给其他人。他需要准备K+8副这样的筷子(给他自己、妻子、儿子、女儿、父亲、母亲、岳父、岳母以及K名客人)。但是L先生的筷子有很多不同的长度!给出所有筷子的长度,他需要找到一种组合K+8副筷子的方法,使得难用度的总和最小。

这道题我们先降序排序,然后再用动态规划去解决,为什么要降序排序呢?因为这三只筷子里有最长的一只,如果我们按已给的递增顺序递推,无法保证存在最长筷子,相反降序递推,因为这组数的最大值不可能成为一双筷子里的一只,只能是作为第三只筷子存在(或者不选)因此就避免了上面的问题。当然实现起来就不用排序了,因为题中已经给了递增顺序,倒过来就行了。

代码如下:

#include<stdio.h>
#define MAXN 5000+10
#define MAXN1 1000+10
int a[MAXN], f[MAXN][MAXN1] = {0};
int T, n, k, i, j;
void solve()
{
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j*3 <= i && j <= k+8; j ++)
        {
            f[i][j] = f[i-2][j-1]  + (a[i-1]-a[i])*(a[i-1]-a[i]);
            if(3*j < i && f[i][j] > f[i-1][j])
                f[i][j] = f[i-1][j];
        }
    }
    printf("%d\n",f[n][k+8]);
}
void input()
{
    while(~scanf("%d", &T))
    while(T --)
    {
        scanf("%d%d",&k, &n);
        for(int i = n; i; i --)
            scanf("%d",&a[i]);
        solve();
    }
}
int main()
{
    input();
    return 0;
}

 

 

posted on 2012-04-25 00:13  BFP  阅读(326)  评论(0编辑  收藏  举报