【动规】筷子
题目描述
叉烧的生日快到了,他决定邀请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;
}