• HDU-3480 Division 【DP+斜率优化(二维)】


    题目链接

    题意

    定义一个集合的花费是这个集合中的最大值减最小值的平方。然后给定一个集合S,求对这个集合的一个覆盖,使得所有子集的花费和最小。

    分析

    本身这个题是非常简单的,只是今天看了别人的题解,我发现我以前写的二维斜率优化都写复杂了。直接外层循环用未被优化的那一维就行了,不用像我以前那样维护一个k维的单调队列……我说怎么不对劲,每次看别人的代码都那么短……
    具体见代码

    AC代码

    //HDU-3480 Division
    //AC  2017-3-11 14:52:18
    //DP, slope trick(2d)
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e4+100,maxm=5e3+100;
    
    int N,M;
    int dp[maxn][2],a[maxn];
    int que[maxn];
    int head,tail;
    
    int getx(int j)
    {
        return a[j+1];
    }
    
    int gety(int j,int flag)
    {
        return dp[j][!flag]+a[j+1]*a[j+1];
    }
    
    void insert(int i,int flag)
    {
        while(tail>head+1&&
              (gety(i,flag)-gety(que[tail-1],flag))*(getx(que[tail-1])-getx(que[tail-2]))<=
              (gety(que[tail-1],flag)-gety(que[tail-2],flag))*(getx(i)-getx(que[tail-1])))
                tail--;
        que[tail++]=i;
        return;
    }
    
    int get_front(int i,int flag)
    {
        while(tail>head+1&&
              (gety(que[head+1],flag)-gety(que[head],flag))<=(getx(que[head+1])-getx(que[head]))*2*a[i])
                ++head;
        return gety(que[head],flag)-2*a[i]*getx(que[head]);
    }
    
    
    int main()
    {
        int T;scanf("%d",&T);
        for(int kase=1;kase<=T;++kase)
        {
            scanf("%d %d",&N,&M);
            if(N<=M)
            {
                printf("Case %d: 0
    ",kase);
                continue;
            }
            for(int i=1;i<=N;++i)
                scanf("%d",a+i);
            sort(a+1,a+1+N);
            memset(dp,0x3f,sizeof dp);
            int flag=0;
            for(int i=1;i<=N;++i)
                dp[i][flag]=(a[i]-a[1])*(a[i]-a[1]);
            flag=!flag;
            for(int k=2;k<=M;++k)
            {
                head=tail=0;
                dp[1][flag]=dp[1][!flag];
                insert(1,flag);
                for(int i=2;i<=N;++i)
                {
                    dp[i][flag]=get_front(i,flag)+a[i]*a[i];
                    insert(i,flag);
                }
                flag=!flag;
            }
            /*for(int i=1;i<=N;++i)
            {
                dp[i][1]=(a[i]-a[1])*(a[i]-a[1]);
                insert(i,1);
                for(int k=2;k<=min(M,i);++k)
                {
                    dp[i][k]=get_front(i,k-1)+a[i]*a[i];
                    insert(i,k);
                }
            }*/
            printf("Case %d: %d
    ",kase,dp[N][!flag]);
        }
        return 0;
    }
  • 相关阅读:
    小程序
    wepy
    html5 +css3 点击后水波纹扩散效果 兼容移动端
    vue+element 切换正式和测试环境
    Nuxt
    vue相关安装命令
    【react】--------------配置react项目根路径-------------【劉】
    【Android】--------------高版本http请求错误-------------【劉】
    【react-native】--------------检测SIM卡是否安装-------------【劉】
    【javascript】--------------http-------------【劉】
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580569.html
Copyright © 2020-2023  润新知