[dp] uva10271 Chopsticks

来源:互联网 发布:python write 编辑:程序博客网 时间:2024/06/07 10:10

Description

    In China, people use a pair of chopsticks to get food on the table, but Mr. L is a bit different. He uses a set of three chopsticks – one pair, plus an EXTRA long chopstick to get some big food by piercing it through the food. As you may guess, *the length of the two shorter chopsticks should be as close as possible, but the length of the extra one is not important, as long as it’s the longest. To make things clearer, for the set of chopsticks with lengths A B C (A ≤ B ≤ C), (A − B)2 is called the “*badness” of the set.
     It’s December 2nd, Mr.L’s birthday! He invited K people to join his birthday party, and would like to introduce his way of using chopsticks. So, he should prepare K + 8 sets of chopsticks(for himself,his wife, his little son, little daughter, his mother, father, mother-in-law, father-in-law, and K other guests). But Mr.L suddenly discovered that his chopsticks are of quite different lengths! He should find a way of composing the K + 8 sets, so that the total badness of all the sets is minimized.

Input

     The first line in the input contains a single integer T , indicating the number of test cases (1 ≤ T ≤ 20). Each test case begins with two integers K, N (0 ≤ K ≤ 1000, 3K + 24 ≤ N ≤ 5000), the number of guests and the number of chopsticks.There are N positive integers on the next line in non–decreasing order indicating the lengths of the chopsticks(1 ≤ Li ≤ 2000) .

Output

    For each test case in the input, print a line containing the minimal total badness of all the sets.Note: For the sample input, a possible collection of the 9 sets is:
8,10,16; 19,22,27; 61,63,75; 71,72,88; 81,81,84; 96,98,103; 128,129,148; 134,134,139; 157,157,160

Sample Input

1
1 40
1 8 10 16 19 22 27 33 36 40 47 52 56 61 63 71 72 75 81 81 84 88 96 98 103 110 113 118 124 128 129 134 134 139 148 157 157 160 162 164

Sample Output

23

题目分析

    先考虑一个更简单的问题:将一组筷子改为两双。定义f[i][j]为前j根筷子组成i组的”the minimal total badness of all the sets”。由于筷子长度组成不减序列,故一组筷子中的两根必定相邻。考虑第j根筷子,它有两种可能:在或不在第i组中。因此得到状态转移方程:
    f[i][j]=min(f[i][j-1],f[i-1][j-2])
    然后考虑此题,一组筷子为三双,最长的一根在计算中没有充当作用,因此只需倒序读入,使筷子形成不增序列,即可忽略其产生的影响,状态转移方程没有变化。
    但此处可能有个疑问,对于f[i][j](j>3*i),有没有可能选出了i组的两根筷子,余下的j-i根不足以挑出较长的i根。举例来说,有没有可能选出以下不合法策略?
这里写图片描述
    这是不会出现的,看转移方程
    f[i][j]=min(f[i][j-1],f[i-1][j-2])
    对于前一种策略,它依赖于以前的f[i][j-1],只要f[i][j-1]策略合法,此策略也合法;对于后一种策略,由于此为单调不增序列,最后两根一定最短,也是合法的。
    最后注意循环时j>=3*i。

代码

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>using namespace std;const int maxn=5001;int a[maxn];int f[1009][maxn];int ds[maxn];int min(int,int);int main(){    int t;    cin>>t;    while(t--)    {        int k,n;        cin>>k>>n;        k+=8;        for(int i=n;i>=1;i--)            scanf("%d",&a[i]);        for(int i=2;i<=n;i++)            ds[i]=(a[i]-a[i-1])*(a[i]-a[i-1]);        memset(f,0x6f,sizeof f);        memset(f[0],0,sizeof f[0]);        for(int i=1;i<=k;i++)        {            for(int j=i*3;j<=n;j++)                f[i][j]=min(f[i][j-1],f[i-1][j-2]+ds[j]);        }        cout<<f[k][n]<<endl;    }    return 0;}int min(int a,int b){return (a<b)?a:b;}
0 0
原创粉丝点击