问题 D: 木棍(dp)
题目描述
在一个原始部落,有一些人要去打猎了,每个人都要挑选自己的工具——两根木棍。一个用作远距离投掷攻击,一个用作近距离搏斗。但是每个人都想挑到最好的,但这是不可能的。但是为了让多数人满意,也为了减少大家的矛盾。部落领袖设计了一个矛盾指数,这个指数就是每个人的不舒服指数和,不舒服指数就(L1-L2)2,其中L1,L2分别是一个人的两根木棍的长度。
部落领袖决定让矛盾指数最少,于是他来向你寻求帮助,希望你能告诉他矛盾指数至少有多少。
部落领袖决定让矛盾指数最少,于是他来向你寻求帮助,希望你能告诉他矛盾指数至少有多少。
输入
第一行两个数m,n.
表示有n个人,m个木棍。
接下来m个数表示每个木棍(肯定有解)。
(m<=2000,n<=500)
表示有n个人,m个木棍。
接下来m个数表示每个木棍(肯定有解)。
(m<=2000,n<=500)
输出
一个数,最少的矛盾指数。
样例输入 Copy
5 2
3
1
4
5
8
样例输出 Copy
5
思路:首先肯定是排序后挨着取最优,然后dp.
dp[i][j]表示第i个人取到第j个棒子最小答案
dp[i][j]=min(dp[i-1][j-2],mi)+(a[j]-a[j+1])*(a[j]-a[j+1]);
mi要一直更新。
#pragma GCC optimize(3 , "Ofast" , "inline")
#include <bits/stdc++.h>
#define rep(i , a , b) for(register int i=(a);i<=(b);i++)
#define per(i , a , b) for(register int i=(a);i>=(b);i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int , int> pi;
template<class T>
inline void read (T &x) {
x = 0;
int sign = 1;
char c = getchar ();
while (c < '0' || c > '9') {
if ( c == '-' ) sign = - 1;
c = getchar ();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar ();
}
x = x * sign;
}
const int maxn = 1e6 + 10;
const int inf = int (1e9);
const ll INF = ll (1e18);
const double PI = acos (- 1);
const int mod = 1e9+7;
const double eps = 1e-8;
int m,n;
ll a[maxn];
ll dp[555][2222];
int main () {
read (m);read (n);
rep (i,1,m) {
read (a[i]);
}
sort (a+1,a+1+m);
rep (i,0,n) {
rep (j,0,m) {
dp[i][j]=INF;
}
}
dp[0][0]=0;
rep (i,1,n) {
ll mi = dp[i-1][i*2-2];
rep (j,i*2,m) {
mi=min (mi,dp[i-1][j-2]);
dp[i][j]=mi+1ll*(a[j]-a[j-1])*(a[j]-a[j-1]);
}
}
ll ans = INF;
rep (i,1,m) {
ans=min (dp[n][i],ans);
}
cout<<ans<<endl;
return 0;
}