目錄
poj2010:Moo University - Financial Aid
1.最大化最小值
poj3258:River Hopscotch
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=5e4+10;
int a[maxn],L,n,m;
bool check(int d){
int pre=a[0],cnt=0;
for(int i=1;i<=n;i++){
if(a[i]-pre<d){
cnt++;
continue;
}
pre=a[i];
}
if(cnt>m||a[n+1]-pre<d) return false;
return true;
}
int main(){
scanf("%d%d%d",&L,&n,&m);
a[0]=0,a[n+1]=L;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n+1);
int l=0,r=L+1; //r的取值要比答案區間大點,所以這裏+1
while(r-l>1){ //這裏的答案區間 [l,r) ,所以二分到區間長度爲1時,答案就出來了
int mid=l+(r-l)/2;
if(check(mid)) l=mid;
else r=mid;
}
printf("%d\n",l);
return 0;
}
poj3273:Monthly Expense
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=1e9+10;
int a[maxn],n,m;
bool check(int d){
int sum,p=1;
for(int i=1;i<=m;i++){
sum=a[p++];
while(p<=n&&sum+a[p]<=d){
sum+=a[p++];
}
if(p>n) return true;
}
return false;
}
int main(){
scanf("%d%d",&n,&m);
int mx=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mx=max(mx,a[i]);
}
int l=mx,r=INF,ans=mx;
while(r-l>=0){ //這裏的答案區間 [l,r] ,所以二分到區間長度爲空時,答案就出來了
int mid=l+(r-l)/2;
if(check(mid)){
ans=mid;
r=mid-1;
}else l=mid+1;
}
printf("%d\n",ans);
return 0;
}
/*
7 5
10 10 10 10 10 10 10
1 1
10000
*/
poj3104:Drying
題解:可以想到對時間進行二分,但對於衣服風乾的總時間無法預定。
大佬很詳細的思路,可以參考下~(在公式推導的地方有點問題,注意下就行)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int a[maxn],n,k;
/*設使用吹風機的時間爲t,則每件衣服最多可以有mid-t的水可以風乾,t*k+(mid-t)>=a[i],t>=(a[i]-mid)/(k-1)*/
bool check(int mid){
long long sum=0; //注意sum有可能超int,最好所有的變量都設爲long long
for(int i=n;i>0;i--){
if(a[i]<=mid) break;
sum+=ceil(1.0*(a[i]-mid)/(k-1));
}
return sum<=mid;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
scanf("%d",&k);
int ans=0;
if(k==1) ans=a[n];
else{
int lb=0,ub=a[n]+1; //[lb,ub]
while(ub-lb>=0){
int mid=lb+(ub-lb)/2;
if(check(mid)){
ans=mid;
ub=mid-1;
//printf("ans=%d\n",ans);
}else lb=mid+1;
}
}
printf("%d\n",ans);
}
return 0;
}
poj3045:Cow Acrobats
最大化平均值
poj2976:Dropping tests
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e3+10;
const double eps=1e-6;
int a[maxn],b[maxn];
double y[maxn];
int n,k;
bool check(double x){
for(int i=0;i<n;i++){
y[i]=a[i]-x*b[i];
}
sort(y,y+n);
double sum=0;
for(int i=n-1;i>=k;i--){
sum+=y[i];
}
return sum>=0;
}
int main(){
while(~scanf("%d%d",&n,&k)){
if(n==0&&k==0) break;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&b[i]);
double lb=0,rb=1;
while(fabs(rb-lb)>=eps){
double mid=lb+(rb-lb)/2;
if(check(mid)) lb=mid;
else rb=mid;
}
printf("%.0f\n",100*lb);
}
return 0;
}
poj3111:K Best
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const double eps=1e-6;
int n,k;
struct Node{
int id;
double v,w,y;
bool operator < (const Node &a) const{
if(y>=a.y) return true;
return false;
}
}res[maxn];
bool check(double x){
for(int i=1;i<=n;i++){
res[i].y=res[i].v-x*res[i].w;
}
sort(res+1,res+1+n);
double sum=0;
for(int i=1;i<=k;i++){
sum+=res[i].y;
}
return sum>=0;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lf%lf",&res[i].v,&res[i].w);
res[i].id=i;
}
double lb=0,rb=1e8;
while(fabs(rb-lb)>=eps){
double mid=lb+(rb-lb)/2;
if(check(mid)) lb=mid;
else rb=mid;
}
//printf("%f\n",lb);
for(int i=1;i<=k;i++){
if(i==1) printf("%d",res[i].id);
else printf(" %d",res[i].id);
}
printf("\n");
return 0;
}
查找第k大的值
poj3579:Median
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int a[maxn],n,m;
int work(int x){
int lb=1,ub=n,ans;
while(lb<=ub){
int mid=lb+(ub-lb)/2;
if(a[mid]<=x){
ans=mid;
lb=mid+1;
}else ub=mid-1;
}
return ans;
}
bool check(int mid){ //在序列裏,如果小於等於mid的數大於等於m個,true
int cnt=0;
for(int i=1;i<=n;i++){
cnt+=work(a[i]+mid)-i;
}
return cnt>=m;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
m=(n*(n-1)/2+1)/2; //中位數的位置
sort(a+1,a+1+n);
int ans=0,lb=0,ub=a[n]-a[1];
while(lb<=ub){
int mid=lb+(ub-lb)/2;
if(check(mid)){
ans=mid;
ub=mid-1;
}else
lb=mid+1;
}
printf("%d\n",ans);
}
return 0;
}
poj3685:Matrix
最小化第k大的值
poj2010:Moo University - Financial Aid
poj3662:Telephone Lines
其他
poj1759:Garland
/*
h[i]=(h[i-1]+h[i+1])/2-1;
h[i+1]=2*(h[i]+1)-h[i-1];
h[3]=2*h[2]+2-A
證明:B的值與h[2]成正相關的。
只要證出這點,直接二分h[2]即可。
證明如下:(大概)
其實遞推的過程中,h[i],h[i+1]化成只含h[2]和常數的式子,
很容易看出h[i]中h[2]的係數大於h[i-1]中h[2]的係數,也就是h[i+1]=a*h[i]+b(a>0)
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const double eps=1e-6;
int n;
double A,ans;
bool check(double x){
double a=A,b=x,tmp;
for(int i=3;i<=n;i++){
tmp=b;
b=2*(b+1)-a;
a=tmp;
if(b<0) return false;
}
ans=b;
return true;
}
int main(){
while(~scanf("%d%lf",&n,&A)){
double lb=0,ub=A;
while(ub-lb>=eps){
double mid=lb+(ub-lb)/2;
if(check(mid)) ub=mid;
else lb=mid;
}
printf("%.2lf\n",ans);
}
return 0;
}
poj3484:Showstopper