zoukankan      html  css  js  c++  java
  • zoj3956(Course Selection System)_Solution

    zoj3956_Solution

    H=sum(hi),C=sum(ci),Value=H*H-H*C-C*C

    Value的最大值

     

    Solution:

    动态规划:

    共两维:H,C           固定一维C,在该维值C相同的情况下另一维应最大H,从而动态规划另一维H,转变为01背包问题。

     

    优化:

    H*H-H*C-C*C=0 (H,C>0)

    H/C=(1+sqrt(5))/2=1.6180…

    必会选择h/c>(1+sqrt(5))/2 的(h,c)对

    证明:

    Value大于0,则H/C>(1+sqrt(5))/2,

    若再加上h/c>(1+sqrt(5))/2 的(h,c)对,

    (H+h)* (H+h)-(H+h) *(C+c)-(C+c)* (C+c)=H*H-H*C-C*C+h*h-h*c-c*c+2*H*h-H*c-h*C-2*C*c

     

    [ (H+h)* (H+h)-(H+h) *(C+c)-(C+c)* (C+c) ] – [ H*H-H*C-C*C ]

    = h*h-h*c-c*c+2*H*h-H*c-h*C-2*C*c

    >2*H*h-H*c-h*C-2*C*c

    >2*H*h - H*h*(1+sqrt(5))/2 - h*H*(1+sqrt(5))/2 – 2*H*(1+sqrt(5))/2*h*(1+sqrt(5))/2

    =0

    值必然会增大,所以必会选择h/c>(1+sqrt(5))/2 的(h,c)对,得证

     

    所以可以把h/c>=(1+sqrt(5))/2的(h,c)对先选出来,再对h/c<(1+sqrt(5))/2的(h,c)对进行动态规划,然后在动态规划的基础上再加上h/c>=(1+sqrt(5))/2的(h,c)对求得在相同C的基础上H的最大值。

     

     

    某个贪心的方法:按照h/c从大到小的顺序依次对h,c对进行排序,然后依次选取,直到值小于0。

    证明不成立:

    原来                 H,C                             value

    加入                 h1,c1                         value1

    再加入             h2,c2                         value2

    h1/c1>h2/c2)

    若原来加入    h2,c2                         value3

     

    证明有可能只加入h2,c2数值更大:

    h1,c1数值非常大,且h1/c1<(1+sqrt(5))/2,加入h1,c1后value1<0,而再加入h2,c2后,value2<value1<0;而尽管h2/c2< h1/c1<(1+sqrt(5))/2,但加入h2,h2后,value2>value。

    H=1700,C=1000

    h1=16000,c1=10000

    h2=159,c1=100

    value=190000

    value1=-2410000

    value2=-2501019

    value3=200981

    当有三个数据(1700,1000),(16000,10000),(159,100),则用此方法求得结果为190000,并不正确。所以该方法错误。

     

     DP:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define maxn 500
     4 
     5 int main()
     6 {
     7     //500*100(total) *500(n) *10(test cases)=250000000
     8 
     9     //max_result=(10000*500)^2
    10     //the maximum of h[i] is larger than c[i],thus choose c
    11     //the total of c is not larger than 500*100=50000
    12     //when c is the same , we need maximum h
    13     long h[maxn+1],c[maxn+1];
    14     //<=10000/100*500
    15     long t,n,i,j,k,ans[maxn+1],f[50001];
    16     long long s,result;
    17     scanf("%ld",&t);
    18     for (k=1;k<=t;k++)
    19     {
    20         ans[0]=0;
    21         result=0;
    22         scanf("%ld",&n);
    23         for (i=1;i<=n;i++)
    24         {
    25             scanf("%ld %ld",&h[i],&c[i]);
    26             ans[i]=ans[i-1]+c[i];
    27         }
    28         for (i=1;i<=ans[n];i++)
    29             f[i]=-1;
    30         f[0]=0;
    31         for (i=1;i<=n;i++)
    32             //when choose course ith ,the maximum of credit is ans[i](including c[i])
    33             for (j=ans[i];j>=c[i];j--)
    34                 if (f[j-c[i]]!=-1 && f[j-c[i]]+h[i]>f[j])
    35                     f[j]=f[j-c[i]]+h[i];
    36         for (i=1;i<=ans[n];i++)
    37             if (f[i]!=-1)
    38             {
    39                 s=f[i]*f[i]-f[i]*i-i*i;
    40                 if (s>result)
    41                 result=s;
    42         }
    43         printf("%lld
    ",result);
    44     }
    45     return 0;
    46 }
    47 /*
    48 100 1 1 1 1 1 1 1 1
    49 0+101+102+……
    50 not obvious
    51 
    52 WorstSituation
    53 10 10 10 10 10
    54 50+50+50+50+50=250
    55 0+10+20+30+40=100
    56 save halt of the time
    57 
    58 Previous:
    59 49900*500=24950000
    60 Current:
    61 0+100+200+…+49900=12500000
    62 10Cases
    63 12500000*10=1,2500,0000
    64 */

     DP(advance):

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define maxn 500
     4 
     5 //原来60s,现在20s
     6 
     7 int main()
     8 {
     9     //500*100(total) *500(n) *10(test cases)=250000000
    10 
    11     //max_result=(10000*500)^2
    12     //the maximum of h[i] is larger than c[i],thus choose c
    13     //the total of c is not larger than 500*100=50000
    14     //when c is the same , we need maximum h
    15     long h[maxn+1],c[maxn+1],ans[maxn+1],f[50001];
    16     //<=10000/100*500
    17     long t,n,i,j,k,g,temp,hh,cc;
    18     long long s,result;
    19     double line=(1.0+sqrt(5.0))/2;
    20     scanf("%ld",&t);
    21     for (k=1;k<=t;k++)
    22     {
    23         ans[0]=0;
    24         scanf("%ld",&n);
    25         for (i=1;i<=n;i++)
    26             scanf("%ld %ld",&h[i],&c[i]);
    27         g=n+1;
    28         for (i=n;i>=1;i--)
    29             if (1.0*h[i]/c[i]>=line)
    30             {
    31                 g--;
    32                 temp=h[i];
    33                 h[i]=h[g];
    34                 h[g]=temp;
    35                 temp=c[i];
    36                 c[i]=c[g];
    37                 c[g]=temp;
    38             }
    39         g--;
    40         //a[g+1]~a[n] h[i]/c[i]>=line must be chose
    41         hh=0;
    42         cc=0;
    43         for (i=g+1;i<=n;i++)
    44         {
    45             hh+=h[i];
    46             cc+=c[i];
    47         }
    48         //a[1]~a[g] h[i]/c[i]<line
    49         for (i=1;i<=g;i++)
    50             ans[i]=ans[i-1]+c[i];
    51         for (i=1;i<=ans[g];i++)
    52             f[i]=-1;
    53         f[0]=0;
    54         for (i=1;i<=g;i++)
    55             //when choose course ith ,the maximum of credit is ans[i](including c[i])
    56             for (j=ans[i];j>=c[i];j--)
    57                 if (f[j-c[i]]!=-1 && f[j-c[i]]+h[i]>f[j])
    58                     f[j]=f[j-c[i]]+h[i];
    59         result=hh*hh-hh*cc-cc*cc;
    60         for (i=1;i<=ans[g];i++)
    61             if (f[i]!=-1)
    62             {
    63                 s=(f[i]+hh)*(f[i]+hh)-(f[i]+hh)*(i+cc)-(i+cc)*(i+cc);
    64                 if (s>result)
    65                 result=s;
    66         }
    67         printf("%lld
    ",result);
    68     }
    69     return 0;
    70 }
    71 /*
    72 100 1 1 1 1 1 1 1 1
    73 0+101+102+……
    74 not obvious
    75 
    76 WorstSituation
    77 10 10 10 10 10
    78 50+50+50+50+50=250
    79 0+10+20+30+40=100
    80 save halt of the time
    81 
    82 Previous:
    83 49900*500=24950000
    84 Current:
    85 0+100+200+…+49900=12500000
    86 10Cases
    87 12500000*10=1,2500,0000
    88 */

    贪心(Wrong):

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define maxn 500
     4 
     5 struct node
     6 {
     7     long h,c;
     8     double per;
     9 };
    10 
    11 int cmp(const void *a,const void *b)
    12 {
    13     if ((*(struct node *)b).per>(*(struct node *)a).per)
    14         return 1;
    15     else
    16         return 0;
    17 }
    18 
    19 long long max(long long a,long long b)
    20 {
    21     if (a>b)
    22         return a;
    23     else
    24         return b;
    25 }
    26 
    27 int main()
    28 {
    29     long t,k,l,n,ht,ct;
    30     long long maxs;
    31     struct node course[maxn+1];
    32     scanf("%ld",&t);
    33     for (k=1;k<=t;k++)
    34     {
    35         scanf("%ld",&n);
    36         for (l=0;l<n;l++)
    37         {
    38             scanf("%ld%ld",&course[l].h,&course[l].c);
    39             course[l].per=1.0*course[l].h/course[l].c;
    40         }
    41         qsort(course,n,sizeof(struct node),cmp);
    42         ht=0;
    43         ct=0;
    44         maxs=0;
    45         for (l=0;l<n;l++)
    46         {
    47             ht+=course[l].h;
    48             ct+=course[l].c;
    49             maxs=max(maxs,ht*ht-ht*ct-ct*ct);
    50         }
    51         printf("%lld
    ",maxs);
    52     }
    53     return 0;
    54 }
    55 /*
    56 5
    57 1 4
    58 2 5
    59 6 3
    60 7 2
    61 4 4
    62 */

    最普通的方法,保证正确,用于测试其它程序是否正确:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 struct node
     5 {
     6     long h,c;
     7     double per;
     8 };
     9     long n;
    10     long long maxs=0;
    11         struct node course[501];
    12 
    13 int cmp(const void *a,const void *b)
    14 {
    15     return (*(struct node *)b).per-(*(struct node *)a).per;
    16 }
    17 
    18 long long max(long long a,long long b)
    19 {
    20     if (a>b)
    21         return a;
    22     else
    23         return b;
    24 }
    25 
    26 void dfs(long d,long ht,long ct)
    27 {
    28     if (d==n)
    29         return ;
    30     if (ct!=0)
    31         maxs=max(maxs,ht*ht-ht*ct-ct*ct);
    32     dfs(d+1,ht+course[d].h,ct+course[d].c);
    33     dfs(d+1,ht,ct);
    34 }
    35 
    36 int main()
    37 {
    38     long t,k,l;
    39     scanf("%ld",&t);
    40     for (k=1;k<=t;k++)
    41     {
    42         scanf("%ld",&n);
    43         maxs=0;
    44         for (l=0;l<n;l++)
    45         {
    46             scanf("%ld%ld",&course[l].h,&course[l].c);
    47             course[l].per=1.0*course[l].h/course[l].c;
    48         }
    49         dfs(0,0,0);
    50 printf("%lld
    ",maxs);
    51     }
    52     return 0;
    53 }

    以下是我做的关于此题做的评测方法,值得一览

    http://pan.baidu.com/s/1c1WeUGS

  • 相关阅读:
    Alpha 冲刺报告(5/10)
    Alpha 冲刺报告(4/10)
    Alpha 冲刺报告(3/10)
    Alpha 冲刺报告(2/10)
    Alpha 冲刺报告(1/10)
    项目需求分析答辩总结
    项目选题报告答辩总结
    项目UML设计(团队)
    第七次作业--项目需求分析(团队)
    第六次作业--结对编程第二次
  • 原文地址:https://www.cnblogs.com/cmyg/p/6816165.html
Copyright © 2011-2022 走看看