• P2672推销员


    传送

    很抱歉之前用错误的思路写了一篇题解ρωρ

    先说一下之前的思路。

    对于每个住户,求出它的s[i]*2+a[i],寻找最大的住户m,然后按照a排序,如果m在前x大的住户里面,就选择前x大的住户,从中选择最大的s,计算答案。否则选择权值前x-1大的住户和m。

    but这个是错的!!!!

    hack数据:

    1 5 6

    3 5 2

    正确答案:15 19 22

    上述思路的答案:15 18 22

    第二个按照上述思路的选法:选择第1,2户。

    正解选法:选择第2,3户。

    错误思路的代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,sum[100009],ma[400009];
    struct zh{
        int bh,l,p,q;
    }r[100009];
    int read()
    {
        char ch=getchar();
        int x=0;bool f=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        f?x=-x:x=x;
        return x;
    }
    bool cmp1(zh a,zh b)
    {
        return a.p>b.p;
    }
    int main()
    {
        int maxn=0,maxi;
        n=read();int m;
        for(int i=1;i<=n;i++)
         r[i].l=read(),r[i].bh=i;
        for(int i=1;i<=n;i++)
         {
             r[i].p=read();
             r[i].q=r[i].l*2+r[i].p;
             if(r[i].q>maxn)
              maxn=r[i].q,maxi=r[i].bh;
         }
         m=r[n].l;
         sort(r+1,r+1+n,cmp1);
         for(int i=1;i<=n;i++)
           sum[i]=sum[i-1]+r[i].p,ma[i]=max(ma[i-1],r[i].l);
         int mi;
         for(int i=1;i<=n;i++)
         {
             if(r[i].bh==maxi)
             {
                 mi=i;
                 break;
            }
         }
         printf("%d
    ",maxn);
         for(int i=2;i<n;i++)
         {int ren=0,lu=r[mi].l*2;
             if(mi<=i)
             {
                 ren=sum[i];
             if(ma[i]>r[mi].l)lu=ma[i]*2;
             int ans=ren+lu;
             printf("%d
    ",ans);
            }
            else
            {    ren=r[mi].p+sum[i-1];
             if(ma[i-1]>r[mi].l)lu=ma[i-1]*2;
             int ans=ren+lu;
             printf("%d
    ",ans);
            }
         }
         int ans=0;
         for(int i=1;i<=n;i++)
           ans+=r[i].p;  
           ans+=m*2;
           printf("%d
    ",ans);
    }
    它是个错的QAQ

    正确的思路是什么鸭?窝也不会鸭~来让我们仔(fan)细(fan)思(ti)考(jie)

    先来说一下上面的思路错在哪里。

    上面对于每个x,都有一种确定的方案(选前x个或者选前x-1个)。但是我们不知道另一种方案是否比我们确定的这个方案要优。

    所以我们把上面的两种选法比较一下。

    先按照a从大到小排序

    用qaq[i]来记录i个住户里面最大的a[i]+s[i]*2(排序后),sum[i]是排序后的前缀和,ma[i]是排序后前i个中的最大的s,则ansi=max(sum[x]+ma[i]*2,sum[x-1]+qaq[x])

    为什么qaq是记录i个住户的信息呢?

    因为后i个住户的a会小,但是s可能会很大。这里是考虑s对ans的影响

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,sum[100009],ma[400009],qaq[400009];
    struct zh{
        int bh,l,p,q;
    }r[100009];
    int read()
    {
        char ch=getchar();
        int x=0;bool f=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        f?x=-x:x=x;
        return x;
    }
    bool cmp1(zh a,zh b)
    {
        return a.p>b.p;
    }
    int main()
    {
        int maxn=0,maxi;
        n=read();int m;
        for(int i=1;i<=n;i++)
         r[i].l=read(),r[i].bh=i;
        for(int i=1;i<=n;i++)
         {
             r[i].p=read();
             r[i].q=r[i].l*2+r[i].p;
             if(r[i].q>maxn)
              maxn=r[i].q,maxi=r[i].bh;
         }
         m=r[n].l;
         sort(r+1,r+1+n,cmp1);
         for(int i=1;i<=n;i++)
           sum[i]=sum[i-1]+r[i].p,ma[i]=max(ma[i-1],r[i].l);
         qaq[n]=r[n].l*2+r[n].p;
         for(int i=n-1;i>=1;i--)
            qaq[i]=max(qaq[i+1],r[i].l*2+r[i].p);
         
         printf("%d
    ",maxn);
         for(int i=2;i<n;i++)
         {
            int ans=max(sum[i]+ma[i]*2,sum[i-1]+qaq[i]);
            printf("%d
    ",ans);
         }
         int ans=0;
         for(int i=1;i<=n;i++)
           ans+=r[i].p;  
           ans+=m*2;
           printf("%d
    ",ans);
    }
    它终于对了
  • 相关阅读:
    win10企业版激活密钥
    百科知识 手机QQ的视频如何保存
    华为荣耀7手机如何开启开发者模式,开启调试模式
    C#如何设置控件水平对齐,垂直对齐
    C#如何实现挂机锁
    JAVA_MyEclipse常见配置NETGEAR路由器如何设置
    JAVA_MyEclipse如何加载Tomcat
    VC++_错误 无法打开包括文件“glglut.h” No such file or directory 怎么办
    生活娱乐 达尔优的键盘鼠标如何打开和关闭呼吸灯
    新版的豌豆荚如何连接电脑
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11124252.html
Copyright © 2020-2023  润新知