这两天一直在做动态规划题:昨天做了杭电的1074 状态压缩dp题,因为是以前从来没接触过状态dp,所以费了很久
时间直到今天才弄明白~下午又看了一道相对简单点的动归题~现在尽量讲明白思路:
1421 题得先弄明白题意,从n个数中选出k对来,使得最终的疲劳度最小。
第一步 从小到大对n个数排序。。。。
第二步 先确定状态:dp[ i ][ j ]表示从前i个数中选取j对的最优解。。
第三步 确定状态转移方程 (如果 第 i 个数被选了,那么它肯定是和第i-1个数作一对)
所以: dp[ i ][ j ]=min(dp[ i-2 ][ j-1 ]+(a[ i ]-a[ i-1 ])*(a[ i ]-a[ i-1 ]),dp[ i-1 ][ j ]);
最后实现代码,注意代码实现的过程中一个点 就是dp初始化的问题;
附上ac代码
#include <iostream>
using namespace std;
int a[2100],dp[2100][1005];
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int n,k;
while(cin>>n>>k)
{
for(int i=1;i<=n;i++)
cin>>a[i];
qsort(a+1,n,sizeof(int),cmp);
for(int i=0;i<=n;i++)
{
for(int j=0;j*2<=n+2;j++)
if(j*2>i)dp[i][j]=100000000;
}
for(int i=0;i<=n;i++)
dp[i][0]=0;
for(int i=2;i<=n;i++)
{
for(int j=1;j*2<=i;j++)
dp[i][j]=min(dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]),dp[i-1][j]);
}
cout<<dp[n][k]<<endl;
}
return 0;
}