动态规划之 筷子
描述
A 先生有很多雙筷子。確切的說應該是很多根,因為筷子的長度不一,很難判斷出哪兩根是一雙的。這天,A 先生家里來了K 個客人,A 先生留下他們吃晚飯。加上A 先生,A夫人和他們的孩子小A,共K+3個人。每人需要用一雙筷子。A 先生只好清理了一下筷子,共N 根,長度為T1,T2,T3,……,TN。現在他想用這些筷子組合成K+3 雙,使每雙的筷子長度差的平方和最小。(怎么不是和最小??這要去問A 先生了,呵呵)
輸入
共有兩行,第一行為兩個用空格隔開的整數,表示N,K(1≤N≤100,0<K<50),第二行共有N個用空格隔開的整數,為Ti每個整數為1~50之間的數。
輸出
僅一行。如果湊不齊K+3雙,輸出-1,否則輸出長度差平方和的最小值。
樣例輸入
10 1
1 1 2 3 3 3 4 6 10 20
樣例輸出
5
?
【思路】
? ? 首先應該想到是dp問題。先sort這樣第i和第i-1根就是差距最小的了,
? ? f[i][j]表示前i根組成j雙筷子每雙長度差的和的最小值。
? ?在考慮第i根筷子時,需要做出的決策即使要不要把這只筷子加入到最優解中去,
? ?若加入,則其與第(i-1)根筷子組成一對,f[i][j]=f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]),否則f[i][j]=f[i-1][j] .?
? ?當然,上述決策過程依賴于以下先驗知識:
? ? 當從小到大排好的 a,b,c,d 四根筷子組成兩雙時, ab,cd 這樣的組合最優. 就是以上決策時采取的 將第i個筷子跟第i-1根組成一對.
? ?故dp方程這樣寫
??f[i][j]=min(f[i-1][j],f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));
【代碼】
?
#include<iostream>#include<cstdio>
#include<cstdlib>
#include<climits>
#include<cstring>
#include<algorithm>
using?namespace?std;
int??f[200][200],a[200];
int?n,k,i,j;
int?min(int?a,int?b)
{
????if(a<b)
????????return?a;
????else
????????return?b;
}
void?init()
{
?scanf("%d%d",&n,&k);
?if((k+3)*2>n)cout<<-1<<endl,exit(0);
?for(i=1;i<=n;i++)
?scanf("%d",&a[i]);
?sort(&a[1],&a[n]+1);
}
int?main()
{
??init();
??memset(f,0x3f,sizeof(f));
??for(i=0;i<=n;i++)f[i][0]=0;
??for(i=2;i<=n;i++)????
??for(j=1;j<=i/2;j++)
??f[i][j]=min(f[i-1][j],f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));
?
??printf("%d\n",f[n][k+3]);
??return?0;
}
?
?
?
轉載于:https://www.cnblogs.com/suncoolcat/p/3424207.html
總結
- 上一篇: 程序猿的终点?!!!
- 下一篇: 第一个基础练习题