HDU 1500(经典的恶心DP)
这是比较经典的DP 有一点很明显 却很难肯定的
那就是在最好的分组方案中,每组中两根较短的筷子在有序筷子数列中一定是相邻的
dp[j][i]表示从前i根筷子中挑出j组(不考虑第三根)
dp[j][i]=min{
dp[j][i-1];(i>j*2)
dp[j-1][i-2]+(hash[i]-hash[i-1])^2;(n-i>(k-j)*3)
}
太恶心了 做得我很郁闷 代码贴上 备忘
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
long hash[5010];
long dp[1010][5010];
int main()
{
long T,K,N;
scanf("%ld",&T);
while (T--)
{
scanf("%ld %ld",&K,&N);
long i,j;
for(i=0;i<N;++i)
{
scanf("%ld",&hash[i]);
}
sort(hash,hash+N,greater<long>());
long t=hash[1]-hash[2];
dp[0][2]=t*t;
for (i=3;i<N;++i)
{
t=hash[i]-hash[i-1];
t*=t;
dp[0][i]=dp[0][i-1]>t?t:dp[0][i-1];
}
for (i=1;i<K+8;++i)
{
long s=3*i+2;
t=hash[s]-hash[s-1];
t*=t;
dp[i][s]=dp[i-1][s-2]+t;
for (j=s+1;j<N;++j)
{
t=hash[j]-hash[j-1];
t*=t;
t=dp[i-1][j-2]+t;
dp[i][j]=dp[i][j-1]>t?t:dp[i][j-1];
}
}
printf("%ld\n",dp[K+7][N-1]);
}
return 0;
}
#include <algorithm>
#include <functional>
using namespace std;
long hash[5010];
long dp[1010][5010];
int main()
{
long T,K,N;
scanf("%ld",&T);
while (T--)
{
scanf("%ld %ld",&K,&N);
long i,j;
for(i=0;i<N;++i)
{
scanf("%ld",&hash[i]);
}
sort(hash,hash+N,greater<long>());
long t=hash[1]-hash[2];
dp[0][2]=t*t;
for (i=3;i<N;++i)
{
t=hash[i]-hash[i-1];
t*=t;
dp[0][i]=dp[0][i-1]>t?t:dp[0][i-1];
}
for (i=1;i<K+8;++i)
{
long s=3*i+2;
t=hash[s]-hash[s-1];
t*=t;
dp[i][s]=dp[i-1][s-2]+t;
for (j=s+1;j<N;++j)
{
t=hash[j]-hash[j-1];
t*=t;
t=dp[i-1][j-2]+t;
dp[i][j]=dp[i][j-1]>t?t:dp[i][j-1];
}
}
printf("%ld\n",dp[K+7][N-1]);
}
return 0;
}