• GHOJ 666 筷子


    题目描述

      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
     

    样例说明

      第一双 1 1

      第二双 2 3

      第三双 3 3

      第四双 4 6

    题解

      容易想到,我们设第$i$个人拥有筷子$c_{2i-1}$、$c_{2i}$,那么对于所有被选的筷子,一定有$c_{j} leqslant c_{j+1}$。

      我们对筷子长度进行排序,然后直接dp即可。

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    
    #define MAX_N 100
    #define MAX_M 50
    
    using namespace std;
    
    int n, m;
    int a[MAX_N | 1];
    int dp[MAX_N | 1][MAX_M + 4];
    
    int main()
    {
        cin >> n >> m;
        m += 3;
        if(n < (m << 1)) return cout << -1, 0;
        for(register int i = 1; i <= n; ++i)
        {
            cin >> a[i];
        }
        sort(a + 1, a + n + 1);
        for(register int k = 1; k <= m; ++k)
        {
            dp[(k << 1) - 1][k] = 2000000000;
            for(register int i = k << 1; i <= n; ++i)
            {
                dp[i][k] = dp[i - 1][k];
                for(register int j = (k << 1) - 1; j < i; ++j)
                {
                    dp[i][k] = min(dp[i][k], dp[j - 1][k - 1] + (a[i] - a[j]) * (a[i] - a[j]));
                }
            }
        }
        cout << dp[n][m];
        return 0;
    }
    参考程序
  • 相关阅读:
    encodeURIcomponent编码和ASP.NET之间编码转换
    android入门学习一 基本概念
    Acvityity 的生命周期
    Android中ADT插件的安装
    控件必须放在具有 runat=server 的窗体标记内 错误解决解决方法
    AspNetPager 重写UrlRewriting配置示例
    将字符串按指定长度换行的一个C#方法
    [添砖加瓦]:ExtJS+WCF+LINQ打造全功能Grid
    C#中判断字符是否为中文
    Asp.net中防止用户多次登录的方法
  • 原文地址:https://www.cnblogs.com/kcn999/p/10885469.html
Copyright © 2020-2023  润新知