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:
#include <stdio.h>
#include <stdlib.h>
#define maxn 500 int main()
{
//500*100(total) *500(n) *10(test cases)=250000000 //max_result=(10000*500)^2
//the maximum of h[i] is larger than c[i],thus choose c
//the total of c is not larger than 500*100=50000
//when c is the same , we need maximum h
long h[maxn+],c[maxn+];
//<=10000/100*500
long t,n,i,j,k,ans[maxn+],f[];
long long s,result;
scanf("%ld",&t);
for (k=;k<=t;k++)
{
ans[]=;
result=;
scanf("%ld",&n);
for (i=;i<=n;i++)
{
scanf("%ld %ld",&h[i],&c[i]);
ans[i]=ans[i-]+c[i];
}
for (i=;i<=ans[n];i++)
f[i]=-;
f[]=;
for (i=;i<=n;i++)
//when choose course ith ,the maximum of credit is ans[i](including c[i])
for (j=ans[i];j>=c[i];j--)
if (f[j-c[i]]!=- && f[j-c[i]]+h[i]>f[j])
f[j]=f[j-c[i]]+h[i];
for (i=;i<=ans[n];i++)
if (f[i]!=-)
{
s=f[i]*f[i]-f[i]*i-i*i;
if (s>result)
result=s;
}
printf("%lld\n",result);
}
return ;
}
/*
100 1 1 1 1 1 1 1 1
0+101+102+……
not obvious WorstSituation
10 10 10 10 10
50+50+50+50+50=250
0+10+20+30+40=100
save halt of the time Previous:
49900*500=24950000
Current:
0+100+200+…+49900=12500000
10Cases
12500000*10=1,2500,0000
*/
DP(advance):
#include <stdio.h>
#include <stdlib.h>
#define maxn 500 //原来60s,现在20s int main()
{
//500*100(total) *500(n) *10(test cases)=250000000 //max_result=(10000*500)^2
//the maximum of h[i] is larger than c[i],thus choose c
//the total of c is not larger than 500*100=50000
//when c is the same , we need maximum h
long h[maxn+],c[maxn+],ans[maxn+],f[];
//<=10000/100*500
long t,n,i,j,k,g,temp,hh,cc;
long long s,result;
double line=(1.0+sqrt(5.0))/;
scanf("%ld",&t);
for (k=;k<=t;k++)
{
ans[]=;
scanf("%ld",&n);
for (i=;i<=n;i++)
scanf("%ld %ld",&h[i],&c[i]);
g=n+;
for (i=n;i>=;i--)
if (1.0*h[i]/c[i]>=line)
{
g--;
temp=h[i];
h[i]=h[g];
h[g]=temp;
temp=c[i];
c[i]=c[g];
c[g]=temp;
}
g--;
//a[g+1]~a[n] h[i]/c[i]>=line must be chose
hh=;
cc=;
for (i=g+;i<=n;i++)
{
hh+=h[i];
cc+=c[i];
}
//a[1]~a[g] h[i]/c[i]<line
for (i=;i<=g;i++)
ans[i]=ans[i-]+c[i];
for (i=;i<=ans[g];i++)
f[i]=-;
f[]=;
for (i=;i<=g;i++)
//when choose course ith ,the maximum of credit is ans[i](including c[i])
for (j=ans[i];j>=c[i];j--)
if (f[j-c[i]]!=- && f[j-c[i]]+h[i]>f[j])
f[j]=f[j-c[i]]+h[i];
result=hh*hh-hh*cc-cc*cc;
for (i=;i<=ans[g];i++)
if (f[i]!=-)
{
s=(f[i]+hh)*(f[i]+hh)-(f[i]+hh)*(i+cc)-(i+cc)*(i+cc);
if (s>result)
result=s;
}
printf("%lld\n",result);
}
return ;
}
/*
100 1 1 1 1 1 1 1 1
0+101+102+……
not obvious WorstSituation
10 10 10 10 10
50+50+50+50+50=250
0+10+20+30+40=100
save halt of the time Previous:
49900*500=24950000
Current:
0+100+200+…+49900=12500000
10Cases
12500000*10=1,2500,0000
*/
贪心(Wrong):
#include <stdio.h>
#include <stdlib.h>
#define maxn 500 struct node
{
long h,c;
double per;
}; int cmp(const void *a,const void *b)
{
if ((*(struct node *)b).per>(*(struct node *)a).per)
return ;
else
return ;
} long long max(long long a,long long b)
{
if (a>b)
return a;
else
return b;
} int main()
{
long t,k,l,n,ht,ct;
long long maxs;
struct node course[maxn+];
scanf("%ld",&t);
for (k=;k<=t;k++)
{
scanf("%ld",&n);
for (l=;l<n;l++)
{
scanf("%ld%ld",&course[l].h,&course[l].c);
course[l].per=1.0*course[l].h/course[l].c;
}
qsort(course,n,sizeof(struct node),cmp);
ht=;
ct=;
maxs=;
for (l=;l<n;l++)
{
ht+=course[l].h;
ct+=course[l].c;
maxs=max(maxs,ht*ht-ht*ct-ct*ct);
}
printf("%lld\n",maxs);
}
return ;
}
/*
5
1 4
2 5
6 3
7 2
4 4
*/
最普通的方法,保证正确,用于测试其它程序是否正确:
#include <stdio.h>
#include <stdlib.h> struct node
{
long h,c;
double per;
};
long n;
long long maxs=;
struct node course[]; int cmp(const void *a,const void *b)
{
return (*(struct node *)b).per-(*(struct node *)a).per;
} long long max(long long a,long long b)
{
if (a>b)
return a;
else
return b;
} void dfs(long d,long ht,long ct)
{
if (d==n)
return ;
if (ct!=)
maxs=max(maxs,ht*ht-ht*ct-ct*ct);
dfs(d+,ht+course[d].h,ct+course[d].c);
dfs(d+,ht,ct);
} int main()
{
long t,k,l;
scanf("%ld",&t);
for (k=;k<=t;k++)
{
scanf("%ld",&n);
maxs=;
for (l=;l<n;l++)
{
scanf("%ld%ld",&course[l].h,&course[l].c);
course[l].per=1.0*course[l].h/course[l].c;
}
dfs(,,);
printf("%lld\n",maxs);
}
return ;
}
以下是我做的关于此题做的评测方法,值得一览
http://pan.baidu.com/s/1c1WeUGS

zoj3956(Course Selection System)_Solution的更多相关文章
- ZOJ-3956 Course Selection System,01背包!
Course Selection System 比赛的时候最后20分钟想到了是01背包,奈何没时间推出怎么背. 题意:n门课程,每门课程都有一个h值和c值,现在给出一个happy的定义,所选的课程的h ...
- ZOJ Course Selection System DP
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5565 Course Selection System Time ...
- Course Selection System ZOJ - 3956 01背包+思维
Course Selection System ZOJ - 3956 这个题目居然是一个01背包,我觉得好难想啊,根本就没有想到. 这个题目把题目给的转化为 ans = a*a-a*b-b*b 这个 ...
- ZOJ 3956 Course Selection System 背包DP
ZOJ3956 观察数据范围, c的值非常小 只有100 所以c的和也很有限 只有50000 是否可以从这里下手? 对于某一个c的和 我们一定希望h的和最大 才有可能是最终答案. 于是有了类似背包的d ...
- ZOJ 3956 Course Selection System
题意 有n节课可供选择,每节课都有两个值Hi和Ci,如果学生选择了m节课(x1,x2,....,xm),则它的舒适值被定义为: //这里没有公式((lll¬ω¬)),因为那个图片我保存不下来≧ ﹏ ≦ ...
- ZOJ - 3956 Course Selection System 【01背包变形】
题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3956 题意 给出N组Hi Ci 然后 要选出若干个 使得 这个式 ...
- ZOJ 3956 Course Selection System [01背包]
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3956 题意:就是给你Hi,Ci的值,问怎么取使得下面那个式子的值最大: 理 ...
- C#静态类和静态成员
1. 静态类 1.1 简介 静态类和类成员用于创建无需创建类的实例就能够访问的数据和函数. 静态类成员可用于分离独立于任何对象标识的数据和行为:无论对象发生什么更改,这些数据和函数都不会随之变化. ...
- 关于Eclipse开发插件(三)
视图之间实现事件监听 两个视图中的组件之间的互动,在开发插件的时候是经常碰到的问题.点击视图1列表的某项时,视图2的文本框显示相应的字符. 第一种主动式: 主动式就是在视图1的代码块中获取对视图2的对 ...
随机推荐
- 批量实现多台服务器之间ssh无密码登录的相互信任关系
最近IDC上架了一批hadoop大数据业务服务器,由于集群环境需要在这些服务器之间实现ssh无密码登录的相互信任关系.具体的实现思路:在其中的任一台服务器上通过"ssh-keygen -t ...
- 使用rem进行自适应页面布局
设计师给到我们前端的设计稿一般是按照iphone6屏幕(iphone6 两倍屏 设备 分辨率(物理尺寸) 屏幕宽高 PPI 状态栏高度 导航栏高度 标签栏高度 iPhone6 750×1334 px ...
- vue element-ui 动态上传
上传填写完毕的幼儿及体测数据文件,上传成功后会自动导入该文件的数据 <el-upload :action="UploadUrl()" :on-success="Up ...
- Java多线程的使用以及原理
Java有两种方式实现多线程. 第一种——继承Thread类,并重写run方法 步骤: 定义类继承Thread类: 重写子类的run方法,将线程需要执行的代码写在run方法中: 创建子类的对象,则创建 ...
- 毕业设计 之 三 mooodle及bigbluebutton使用笔记(未完成)
毕业设计 之 三 mooodle及bigbluebutton使用笔记 作者:20135216 平台:windows10 备注:N把辛酸泪 附:在准备过程中其他的一些零碎小问题 一.关于moodle 1 ...
- [2017BUAA软件工程]第0次博客作业
[2017BUAA软件工程]第0次博客作业 结缘计算机 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 计算机是你喜欢的领域吗?是你擅长的领域吗? 我当时报考高考志愿的时候就已经是想好报 ...
- 软件工程_6th weeks
一.上次博客时说的UI,拖拉到现在才展示,完成了“登录,普通匹配,做题界面,做题结果”四项 功能: 二.单元测试工具 1.python单元测试工具 最近因为论文原因一直在用Python,Pytho ...
- hive数据导入load导入命令
LOCAL 指的是操作系统的文件路径,否则默认为HDFS的文件路径 1.向t2和t3的数据表中导入数据 2.导入操作系统的一下三个文件 执行导入命令 3.将HDFS文件中的数据导入到t3中 4.导入 ...
- Mysql 悲观锁
转载:http://chenzhou123520.iteye.com/blog/1860954 悲观锁介绍: 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处 ...
- 一本通1546【NOIP2011】选择客栈
1546:NOIP2011 选择客栈 时间限制: 1000 ms 内存限制: 524288 KB 题目描述 丽江河边有 n 家很有特色的客栈,客栈按照其位置顺序从 1 到 n 编号. ...