问题 D: 木棍(dp)

问题 D: 木棍(dp)

题目描述
在一个原始部落,有一些人要去打猎了,每个人都要挑选自己的工具——两根木棍。一个用作远距离投掷攻击,一个用作近距离搏斗。但是每个人都想挑到最好的,但这是不可能的。但是为了让多数人满意,也为了减少大家的矛盾。部落领袖设计了一个矛盾指数,这个指数就是每个人的不舒服指数和,不舒服指数就(L1-L2)2,其中L1,L2分别是一个人的两根木棍的长度。
部落领袖决定让矛盾指数最少,于是他来向你寻求帮助,希望你能告诉他矛盾指数至少有多少。
输入
第一行两个数m,n.
表示有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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值