HDU-1421--寝室を移動する

タイトル説明:

寮の移転は大変疲れており、xhdには深い経験があります。2006年7月9日、10日に建物が閉鎖されたため、xhdは27号館から3号館への移転を余儀なくされました。寮。nアイテム、xhdは2000未満の整数であるため、ぼんやりし始めました。それは多すぎるため、xhdは過去に2 k個を移動することにしました。しかし、2 kであるため、それでも非常に疲れます。は小さすぎず、noではありません。nより大きい整数です。幸い、xhdは、物を動かす長年の経験に基づいて、各動きの疲労が左右の重量差の2乗に比例することを発見しました。たとえば、xhdが左手に3の重さのアイテムを持ち、右手に6の重さのアイテムを持っている場合、今回移動した後の疲労レベルは(6-3)^ 2 = 9です。 。今、貧しいxhdは、これらの2 * kアイテムを移動した後の最良の状態(つまり、最も低い疲労)を知りたがっています。彼に教えてください。

入る:

入力データの各セットには2つの行があり、最初の行には2つの数値n、k(2 <= 2 * k <= n <2000)があります。2番目の行にはn個のアイテムの重みを表すn個の整数があります(重みは1 A 2 ^ 15未満の正の整数)。

出力:

入力データの各セットに対応して、彼の最小の倦怠感を表す出力データは、各行に1つだけあります。

アイデア:

  • 分析によると、疲労値を最小限に抑えるには、毎回移動するアイテムの重量差が最小である必要があるため、最初にデータを並べ替える必要があります。
  • 2次元配列dp [i] [j]を使用して、j回移動した最初のi個のアイテムの最小疲労を表します。まず、最初の2個のアイテムが1回移動し、最小疲労が正方形であることがわかります。最初の2つの重みの違い、次に最初の3つの各アイテムを一度に移動するのはどうですか?このとき、動的計画法の利点が反映されます。3番目の項目は選択可能かどうか。選択されていない場合は、最初の2つの項目を1回移動した結果です。すでに計算されています。繰り返す必要はありません。計算。を選択した場合は、2番目と3番目の項目の差の2乗、というようになります。最初の4つの項目について、最初の3つの項目と3番目と4番目の項目のいずれか小さい方の値を見つけます。 n番目の項目まで小さい
  • 次に2回移動します。2回移動する場合は4個から始める必要があります。4個を2回移動する最小値は1と2、3と4ですが、5個を2回移動するのはどうでしょうか。5番目のアイテムを選択しない場合、答えは最初の4つのアイテムを2回移動することです。選択した場合、最初の3つのアイテムと4番目と5番目のアイテムを1回移動することです。n個がk回移動するまで
  • 伝達方程式:
    dp[j][i]=min(dp[j-1][i],dp[j-2][i-1]+pow(a[j]-a[j-1],2));

コード:

#include <iostream>
#include <cstring>
#include <algorithm> 
#include <cmath>
using namespace std;
int n,k,ans;
int a[2005];
int dp[2001][1001];//dp[i][j]表示前i件物品,搬j次最低疲劳度 
int min(int x,int y)
{
    
    
	return x<y?x:y;
}
int main()
{
    
    
	while(cin>>n>>k)
	{
    
    
		ans=0;
		memset(dp,0,sizeof(dp)); 
		for(int i=1;i<=n;i++)
		{
    
    
			cin>>a[i];
		}
		sort(a+1,a+n+1);
		for(int i=1;i<=k;i++)//搬的次数 
		{
    
    
			dp[i*2][i]=dp[i*2-2][i-1]+pow(a[i*2]-a[i*2-1],2);//先计算前i*2件搬i次消耗的疲劳值
			for(int j=i*2+1;j<=n;j++)//物品数 
			{
    
    
				dp[j][i]=min(dp[j-1][i],dp[j-2][i-1]+pow(a[j]-a[j-1],2));
			}
		}
		cout<<dp[n][k]<<endl;		
	}
	
	return 0;
} 

おすすめ

転載: blog.csdn.net/weixin_45102820/article/details/114037502