题意:有一个怪人吃饭喜欢用三根筷子,现在他想请他的朋友n个人+8(一定会有的家人亲戚),每个人也要分配3根筷子,现在给你n和筷子总数k,然后下一行是k根筷子的长度;现在要求A<=B<=C;求出总数(A - B ) ^ 2最小的值;
解析;转移方程:dp[ i ][ j ] = min( dp[ i ] [ j - 1 ], dp[ i - 1 ] [ j - 2 ] + num[ j ] ,第一维代表人数,第二维代表筷子数,即第一个为第i个人现在选第C根筷子和第i - 1 个人选A,B,筷子(num[ j ] 的代价)
// Chopsticks.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define INF 999999999
const int maxn = 5005;
int num1[ maxn ], num2[ maxn ], dp[ 1005 ][ maxn ], n, k;
int cmp( int a, int b ){
return a > b;
}
void Start(){
cin >> n >> k;
n += 8;
for( int i = 1; i <= k; ++i )
cin >> num1[ i ];
sort( num1 + 1, num1 + k + 1, cmp);
//for( int i = 1; i <= k; ++i )
// cout << "aaaaaaaa" << num1[ i ] << endl;
memset( dp, 0, sizeof( dp ) );
for( int i = 1; i <= n; ++i ){
for( int j = 1; j <= k; ++j ){
dp[ i ][ j ] = INF;
}
}
for( int i = 1; i <= k; ++i ){
num2[ i ] = ( num1[ i ] - num1[ i - 1 ] ) * ( num1[ i ] - num1[ i - 1 ] );
}
}
//int _tmain(int argc, _TCHAR* argv[])
int main()
{
int Case;
cin >> Case;
while( Case-- ){
Start();
for( int i = 1; i <= n; ++i ){
for( int j = 3 * i; j <= k - ( n - i ) * 2; ++j ){
dp[ i ][ j ] = min( dp[ i ][ j - 1 ], dp[ i - 1 ][ j - 2 ] + num2[ j ] );
}
}
cout << dp[ n ][ k ] << endl;
}
return 0;
}