题意:
给出一堆单只筷子,现在要分成三只筷子一组,长度分别为ABC.。
现在要令每组的(A - B)^2和最大并且在每组中C为最长的。
解析:
是这题给了我 hdu 5135 Little Zu Chongzhi's Triangles(分组dp) 这道题的思路,并瞎扯出了一种叫分组dp的东西。
首先将所有筷子按逆序输入,保证筷子的长度按从小到大增长,这样可以保证C为其中最长的。
然后 dp [ i ] [ j ] 表示组成了i组筷子,使用了j根筷子的最大方和。
所以,状态转移方程为:dp[i][j] = min(dp[i][j - 1], dp[i - 1][j - 2] + fun(l[j - 1] - l[j]))
当前状态下,若不用第j只筷子作为C,则为dp[i][j - 1],若用第j只筷子作为C,则状态为上一组上两只筷子的状态加上j-1与j组成的A和B。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#define LL long long
using namespace std;
const int maxn = 5000 + 10;
const int maxk = 1000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
int l[maxn];
int dp[maxk][maxn];
int fun(int x)
{
return x * x;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int k, n;
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
scanf("%d%d", &k, &n);
k += 8;
for (int i = n; i >= 1; i--)//big to small C>=B>=A
{
scanf("%d", &l[i]);
}
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= n; j++)
{
dp[i][j] = inf;
}
}
for (int j = 2; j <= n; j++)
{
for (int i = 1; i <= k; i++)
{
if (3 * i <= j)// 3zhi kuaizi and C >= B >= A, so the pre combination will not bigger than the 3 * i th l.
{
// not use j as C, use j as C
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j - 2] + fun(l[j - 1] - l[j]));
}
}
}
printf("%d\n", dp[k][n]);
}
return 0;
}