P - 搬寝室
[by_041]
理解题目:
-
首先这是dp题、
-
那么就是要分析:
-
确定状态:用数组
dp[i][j]
表示前i件物品取了j对的最小疲劳值 -
转移方程:
dp[i][j]=minn(dp[i-1][j],dp[i-2][j-1]+sq(a[i]-a[i-1]));
-
起始条件:
sort(v_a+1,v_a+v_n+1);
v_dp[2][1]=v_sq(v_a[2]-v_a[1]);
for(int i=3;i<=v_n;i++)
v_dp[i][1]=minn(v_sq(v_a[i]-v_a[i-1]),v_dp[i-1][1]);
-
终止条件:自然是前n个取到k对咯
-
于是有了AC码:
#include<cstdio>
#include<algorithm>
using namespace std;
void swp(int&a,int&b)
{
a^=b;b^=a;a^=b;return;}
int maxx(int a,int b)
{
return a>b?a:b;}
int minn(int a,int b)
{
return a<b?a:b;}
int input()
{
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
int a=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
a=(a<<3)+(a<<1)+ch-'0';
return a;
}
void output(int a)
{
if(a>9)
output(a/10);
putchar(a%10+'0');
return;
}
int v_sq(int a)
{
return a*a;}
int v_n,v_k,v_a[2002],v_dp[2002][2002];//从前i件选j对物品的最小疲劳
int main()
{
while(scanf("%d%d",&v_n,&v_k)!=EOF)
{
for(int i=1;i<=v_n;i++)
v_a[i]=input();
sort(v_a+1,v_a+v_n+1);
v_dp[2][1]=v_sq(v_a[2]-v_a[1]);
for(int i=3;i<=v_n;i++)
v_dp[i][1]=minn(v_sq(v_a[i]-v_a[i-1]),v_dp[i-1][1]);
for(int j=2;j<=v_k;j++)
{
v_dp[j<<1][j]=v_dp[(j<<1)-2][j-1]+v_sq(v_a[j<<1]-v_a[(j<<1)-1]);
for(int i=(j<<1)+1;i<=v_n;i++)
v_dp[i][j]=minn(v_dp[i-1][j],v_dp[i-2][j-1]+v_sq(v_a[i]-v_a[i-1]));
}
output(v_dp[v_n][v_k]);
putchar('\n');
}
return 0;
}