题目:点击打开链接
一个简单的DP题目,我们可以这样思考,为了使疲劳度最低,我们则需要左右手拿的物品接近,则是a1<a2<a3<a4<a5<a6,这样的序列数,我们则是采取拿a1,a2和拿a3,a4,这样的结果则是疲劳度最低。
DP[i][j]表示拿i件物品需要搬j对.
状态转移方程则是dp[i][j]=min(DP(i-1,j),DP(i-2,j-1)+a[i-1]);
分析:第i件物品不搬,则是在前i-1件物品中搬j对
第i件物品搬,则i-1件物品也要搬,那么则是在前i-2件物品中搬j-1对,再搬第i件
需要注意的是:
1.当2*j<i时,即要搬得数量超过了物品总量,这是不可能发生的,因此此时令dp[i][j]为无穷大.
2.当j==0时,即在一对物品都没搬时,疲劳值为0,此时dp[i][j]=0.
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <stdlib.h> #include <algorithm> #include <map> #include <queue> using namespace std; const int INF=0x7ffffff; int dp[2001][2001]; int a[2010]; int DP(int i,int j) { if(j*2>i) return INF; if(j==0) return 0; return dp[i][j]; } int main() { int n,k,i,j; while(cin>>n>>k) { for(i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1); for(i=1;i<n;i++) { a[i]=a[i+1]-a[i]; a[i]*=a[i]; } for(j=1;j<=k;j++) { for(i=2;i<=n;i++) { dp[i][j]=min(DP(i-1,j),DP(i-2,j-1)+a[i-1]); } } cout<<dp[n][k]<<endl; } return 0; }