zoukankan      html  css  js  c++  java
  • noj[1581] 筷子

    题目描述

    A先生有很多双筷子。确切的说应该是很多根,因为筷子的长度不一,很难判断出哪两根是一双的。这天,A先生家里来了K个客人,A先生留下他们吃晚饭。加上A先生,A夫人和他们的孩子小A,共K+3个人。每人需要用一双筷子。A先生只好清理了一下筷子,共N根,长度为T1,T2,T3,……,TN.现在他想用这些筷子组合成K+3双,f使每双的筷子长度差的平方和最小。(怎么不是和最小??这要去问A先生了,呵呵)

    输入

    输入文件共有两行,第一行为两个用空格隔开的整数,表示N,K(1≤N≤100, 0<K<50),第二行共有N个用空格隔开的整数,为Ti.每个整数为1~50之间的数。

    输出

    输出文件仅一行。如果凑不齐K+3双,输出-1,否则输出长度差平方和的最小值。

    样例

    CHOP.IN

    10 1
    1 1 2 3 3 3 4 6 10 20

    CHOP.OUT

    5

    说明

    第一双 1 1

    第二双 2 3

    第三双 3 3

    第四双 4 6

    (1-1)^2+(2-3)^2+(3-3)^2+(4-6)^2=5

    题解

    先判断是否能凑齐k+3双筷子。

    把n双筷子排序后,相邻的筷子一定排在一起。

    那么,设f[i][j]表示1~j根筷子组成i双的最小平方差之和

    再把问题分为取和不取两种情况,

    1)继承前1~j-1根筷子组成i双的最小平方差之和

    2)从1~j-1根筷子组成i-1双的最小平方差之和来推导

    因此,状态转移方程为:

    f[i][j]=min{f[i][j-1],f[i-1][j-2]+(len[j]-len[j-1])*(len[j]-len[j-1])}

    #include<stdio.h>
    #include<memory.h>
    #define sq(x) ((x)*(x))
    #define dmin(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    bool flag;
    int n,k,t[51],d[101],f[51][101];
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            t[x]++;
        }
        k+=3;
        if((n>>1)<k){
            puts("-1");
            return 0;
        }
        for(int i=1;i<=50;i++)
            for(;t[i];t[i]--)
                d[++d[0]]=i;
        memset(f,60,sizeof(f));
        f[0][0]=0;
        for(int i=1;i<=k;i++)
            for(int j=2;j<=d[0];j++)
                f[i][j]=dmin(f[i][j],dmin(f[i-1][j-2]+sq(d[j]-d[j-1]),f[i][j-1]));
        printf("%d
    ",f[k][d[0]]);
        return 0;
    }
  • 相关阅读:
    城域波分组网的若干关键因素考虑
    浅析影响MSTP设备以太网宽带的因素
    通过网络访问adb
    ubuntu和ok6410开发板之间架设nfs
    mysql connector c++与 visual studio 2012 联合使用
    移植mysql到arm平台
    Python Numpy数组保存
    [转] 如何查看mysql的存储引擎类型
    通过session判断判断用户的操作权限
    PHP图形图像的典型应用 简单图像的应用(水印)
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6069924.html
Copyright © 2011-2022 走看看