【动规】筷子

原题传送门

题目描述

叉烧的生日快到了,他决定邀请K-1个朋友来他家吃饭,加上叉烧一共有K个人。
叉烧有N根筷子,这些筷子很奇特,长短不一。现在叉烧需要整理出K双筷子,使每双筷子长度差的平方和最小。

输入格式

第一行为两个用空格隔开的整数N,K(1≤N≤100, 0≤K≤50),表示有N根筷子,K个人。
第二行共有N个用空格隔开的整数为Ti,表示每根筷子的长度。1≤Ti≤50

输出格式

如果凑不齐K双筷子,输出-1,否则输出一个整数,代表使每双筷子长度差的平方和。

样例输入

4 1
1 3 6 10

样例输出

4


说点啥

这道题难度有点大,至少对我如此,难点在于找到动态规划的i和j分别代表什么才能表示出每个状态,找到这个之后就比较简单了,比赛当时我没找到,赛后才灵光一现反应过来。

先排序,然后i表示已凑集几双筷子,j表示处理到第几双筷子,剩下就很简单,大家都明白了

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int n,k,t[105],c[105],dp[55][105],Max=99999999;
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	cin>>t[i];
	
	sort(t+1,t+n+1);
	for(int i=2;i<=n;i++)
		c[i]=(t[i]-t[i-1])*(t[i]-t[i-1]);
	for(int i=1;i<=k;i++)
		for(int j=1;j<=i*2-1;j++)
			dp[i][j]=Max;
	
	for(int i=1;i<=k;i++)
		for(int j=1;j<=n;j++)
			if(dp[i][j]!=Max)
				dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+c[j]);
				
	if(dp[k][n]==Max)
		cout<<"-1"<<endl;
	else
		cout<<dp[k][n]<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/gongdakai/p/13579577.html