`

UVA 10271 Chopsticks

阅读更多
//  [解题方法]
//  将筷子按长度从大到小排序
//  排序原因:
//    由于一组中A<=B<=C
//    选第i根筷子作为A时,必然要选第i-1根作为B,否则不会达到最优
//  dp[i][j]表示选了对于前j根筷子选了i个筷子集合时的最小花费
//  设c[j]为选j作为A,j-1作为B时的花费(c[j]=(w[i]-w[i-1])^2;),状态转移如下:
//  dp[i][j] = min( dp[i-1][j-2]+c[j](j>=3*i),   dp[i][j-1](j>=3*i+1)     );
//                  要j和j-1作为AB形成新的筷子组     不要j作为A形成新筷子组
//  由于还有C,C>=B>=A,所以j被限制了范围,所以对于dp[i][j]:
//  形成i个筷子组中最后一组的A最低只能在3*i形成,所以确定了j的范围

//  注:这里用了滚动数组优化空间

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define LL long long
#define N 1005
#define M 5005
#define inf 0x3fffffff

LL dp[M], w[M], c[M];

int main()
{
    int t, i, j, n, k;
    cin >> t;
    while (t--)
    {
        cin >> k >> n;
        k += 8;
        for (i = n; i >= 1; i--)
            cin >> w[i];
        for (i = 2; i <= n; i++)
            c[i] = (w[i]-w[i-1])*(w[i]-w[i-1]);
        memset (dp, 0, sizeof(dp));
        for (i = 1; i <= k; i++)
        {
            int m = 3*i;
            for (j = n; j >= m; j--)
                dp[j] = dp[j-2]+c[j];
            for (j = m+1; j <= n; j++)
                if (dp[j-1] < dp[j])
                    dp[j] = dp[j-1];
        }
        cout << dp[n] << endl;
    }
    return 0;
}
1
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics