hdu-1421搬寝室(dp)

http://acm.hdu.edu.cn/showproblem.php?pid=1421;

思路:先将所给的椅子的价值按升序排列,举个例子,四张椅子的价值分别为a,b,c,d(a<b<c<d);

那么分别两两组合(ab)(cd);

(ac)(bd);(ad)(bc);

三种价值分别为(a-b)2+(c-d)2,(a-c)2+(b-d)2,(a-d)2+(b-c)2

那么要比较它们的大小只要比较非平方项的大小就可以了。

(ab+cd),(ac+bd),(ad+bc);

两两项相减比较的第一项最大,那么也就是负的最大,那么第一个式子的值是最小的。

所以要搬椅子肯定要搬相邻的两项。

动态转移方程---

if(j==2*i)
{
dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]);
}

else
{
dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]));
}

dp[i][j]表示当选i组时第j个数选不选的的最小值,如果正好达到第2*i个数dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]),就必须要先初始化,使之包含有2*i个数,

然后dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]))表示第j个数选不选,如果不选就是dp[i][j-1],如果选就要连着前一个数一起选,

那么就是dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]);

最后结果是dp[p][q];

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<iostream>
 6 #include<queue>
 7 const long long N=1e16;
 8 using namespace std;
 9 long long a[3000];
10 long long dp[3000][3000];
11 int main(void)
12 {
13     int i,j,k,p,q;
14     while(scanf("%d %d",&p,&q)!=EOF)
15     {
16         for(i=1; i<=p; i++)
17         {
18             scanf("%lld",&a[i]);
19         }
20         sort(a+1,a+1+p);
21         for(i=0; i<=p; i++)
22         {
23             dp[0][i]=0;
24         }//初始化
25         for(i=1; i<=q; i++)
26         {
27             for(j=2*i; j<=p; j++)
28             {
29                 if(j==2*i)
30                 {
31                     dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]);
32                 }
33                 else
34                 {
35                      dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]));
36                 }
37             }
38         }
39         printf("%lld
",dp[q][p]);
40     }
41     return 0;
42 }
油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5015283.html