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\n",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\n",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\n",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\n",maxs);
51     }
52     return 0;
53 }

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

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

时间: 2024-11-03 21:23:27

zoj3956(Course Selection System)_Solution的相关文章

[省赛训练(DP)]Course Selection System

题面: There are n courses in the course selection system of Marjar University. The i-th course is described by two values: happiness Hi and credit Ci. If a student selects m courses x1, x2, ..., xm, then his comfort level of the semester can be defined

ZOJ 3956 Course Selection System 背包DP

ZOJ3956 观察数据范围, c的值非常小 只有100 所以c的和也很有限 只有50000 是否可以从这里下手? 对于某一个c的和 我们一定希望h的和最大 才有可能是最终答案. 于是有了类似背包的dp方程. 代码很简单,就不给出方程了. //比赛的时候想得太多,都想到斜率优化上了,完全忽略了c的范围这么小!!!毕竟图样. //一个人的面命运,当然要靠自我奋斗,但是也要考虑到历史的行程. #include<iostream> #include<cstdio> #include<

JAVA | 学生选课系统

这里使用JAVA语言编写的简易的学生选课系统,展现的都是这个系统核心代码. 其中有不足欢迎批评和指正! 链接数据库的代码 package connection;//连接数据库student import java.sql.Connection;import java.sql.DriverManager;//import java.sql.Statement;import java.sql.SQLException; public class xu{ private static Connecti

背包入门

A - Bone Collector HDU - 2602 题意:给定背包的最大体积和物品的数量,每一个物品的价值和体积,01背包板子 题解:01背包 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<c

2017 浙大校赛 [Cloned]

https://vjudge.net/contest/285902#overview A.Marjar Cola #include <bits/stdc++.h> using namespace std; int T; int main() { scanf("%d", &T); while(T --) { int x, y, a, b; int ans = 0; scanf("%d%d%d%d", &x, &y, &a,

[转]ADT中通过DDMS导入文件出错ddms transfer error: Read-only file system,Failed to push selection: Read-only file system

[已解决] 原文  http://www.crifan.com/ddms_import_file_error_transfer_error_read_only_file_system/ 想要通过adt的ddms的file explorer去向adv中导入文件,结果出错: [2013-04-23 10:32:00 - ddms] transfer error: Read-only file system [2013-04-23 10:32:00] Failed to push selection:

Failed to push selection: Read-only file system的解决方法

1.获得root权限:adb root 2.设置/system为可读写:adb remount 3.将hosts文件复制到PC:adb pull /system/usr/keylayout/mtk-kpd.kl <PC机上文件名> 4.修改PC机上文件 5.将PC机上文件复制到手机:adb push <PC机上文件名> /system/usr/keylayout/mtk-kpd.kl

Failed to push selection: Read-only file system 调试

这两天调试一个多媒体应用的过程中,因为是在Eclipse直接调试的,所以需要导入多媒体文件到AVD里面调.但是结果出现了上述的log 记得以前调试的时候貌似没遇到过这个问题,所以查了下资料,最后也发现了sdcard那个目录的权限只有一个可怜的d也就是只读,随即按照网上的经验去AVD目录下找了相应的AVD文件夹去修改属性,过程不表..但是结果却是因为所用系统是WIN7,只读属性始终去不掉,于是最后果断放弃. 抱着一线希望可以在AVD Manager中可以在AVD设备的edit里可以找到修改属性的选

王立平--Failed to push selection: Read-only file system

往android模拟器导入资源,失败.提示:只读文件. mnt是只读文件.应点击sdcard,,在导入