就是HDU的搬寝室问题;
DP经典题;
因为最多每次只能拿两个,所以左手右手直接的差值应该尽可能的小;
因此需要快排;
然后:状态转移方程:min(前一个状态所需要的体力+当前状态所需要的 ,前一个状态所需要的体力);
Description
开学了,万恶的大二学长们又要领着大一的鲜肉们一起敲代码搬砖了,这不,著名的杨神拿着n块砖头,当然他把这n块砖头的重量都告诉你了,让你搬走其中的2*k块,其中每次你只能拿2块,消耗的体力是这两块砖头重量之差的平方,比如一块砖重量为5,另一块是11,那么搬走这两块砖头消耗体力为(11- 5)^2 = 36,机智如你,你能算出如何搬2*k块,才能使你花费的体力最小呢?
Input
一个整数t,代表数据组数(t <= 10)
每组数据包含2个整数n和k,保证0 <= 2*k <= n <= 2000
接下来一行包含n个整数(每个数都<= 100000)
每组数据包含2个整数n和k,保证0 <= 2*k <= n <= 2000
接下来一行包含n个整数(每个数都<= 100000)
Output
每组一个整数,代表最小的体力消耗
Sample Input
2 2 1 1 3 6 2 1 4 2 6 11 9
Sample Output
4 5
Hint
第二组样例,可以这么搬(1 2) (4 6)组合,或者(1 2) (9 11)组合,这样花费代价是最少的
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define INF 99999999 #define MAX 2001 using namespace std; int s[MAX][MAX/2+1]; int a[MAX]; int n,k,t; int main() { int t ; cin>>t; while(t--) { cin>>n>>k; for(int i=0;i<n;++i) { cin>>a[i]; } sort(a,a+n); for(int j=1;j<=k;j++) { for(int i=1;i<=n;i++) { if(2*j<=i) { s[i][j]=min(s[i-2][j-1]+(a[i-1]-a[i-2])*(a[i-1]-a[i-2]),s[i-1][j]); } else s[i][j]=INF; } } cout<<s[n][k]<<endl; } return 0; }