[HDU] 1421 搬寝室 要贪心初始化 需要一点时间去磕

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1421

方法:首先对于这些重量乱序的物品,需要排序来贪心初始化然每件物品在选择的时候,都是选择与其重量最接近的。然后建立状态转移方程,设F(k,i)为当选择第i物品的时候,从中选择k对物品的最小疲劳度,staff[i]为排序好了的物品中第i个的重量,方程如下:

    {

      (taff[2] - staff[1])^2, k==1 and i==2;

F(k,i) =     Max( (staff[i]- staff[i-1])^2 , F(k,i-1) ), k==1 and i>=3;

      Max( (staff[i]- staff[i-1])^2+F(k-1,i-2), F(k,i-1)), 1<k<=(i/2向下取整) and i>=3 ; 

      +INF, other condition;

    }

问题最终解为:F(K,N)

基本思想就是 当探寻到第i个物品的时候,在选取k对的时候要做这样的考虑,首先当第i个物品的时候,无论i是奇数还是偶数,其都最少选出1对最多选出i/2向下取整对。这样就确定了k的范围。然后:

当k>1的时候1,第i个物品个之前前一个物品组合的疲劳度加上前面i-2个物品选择k-1对物品的疲劳度。2,不用第i个物品,直接从前面i-1个物品中选k对的疲劳度,如果前面i-1个物品选不出来k对,那么疲劳度为正无穷。最后比较这个两个疲劳度得到当前最优解。

当k==1,考虑1,第i个物品个之前前一个物品组合的疲劳度;2,2,不用第i个物品,直接从前面i-1个物品中选1对的疲劳度。最后比较得当前最优解。

感想:还是磕了很久的,要努力回忆并记住自己是怎么想出来的,这个比ac还重要。

代码:

View Code
#include<iostream>
#include<math.h>
#include<algorithm>
//#include<queue>
//#include<stack>
using namespace std;
int const MAX =0x3f3f3f3f;
int MyMin(int x,int y)
{
    return x<y ? x:y;
}
    int dp[1001][2001];
int main()
{
    int n,k;
    int staff[2001];
 
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        memset(dp,MAX,sizeof(dp));
        for(int i=1;i<=n;i++)
            scanf("%d",&staff[i]);
        sort(staff+1,staff+1+n);
        dp[1][2] = (staff[2]- staff[1])*(staff[2]- staff[1]);
        for(int i = 3;i<=n;i++)
        {
            for(int x =1;x<=i/2;x++)
            {
                if(x==1)
                    dp[x][i] = MyMin(dp[x][i-1],(staff[i]-staff[i-1])*(staff[i]-staff[i-1]) ); 
                else
                    dp[x][i] = MyMin(dp[x][i-1],dp[x-1][i-2]+(staff[i]-staff[i-1])*(staff[i]-staff[i-1]) ); 
            }
        }
        cout<<dp[k][n]<<endl;
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/kbyd/p/3038752.html