zoukankan      html  css  js  c++  java
  • 增援前线

    增援前线

    2020 分做法

    考虑暴力。答案为aia_i的和

    5050 分做法

    枚举全排列

    100100 分做法

    我们可以用二分法或贪心。

    这里会用到一个性质。

    说人要尽量走得远一点。 什么意思?为什么?

    画一个图:

    假设:L=4L=4

    比如说这个魂师,他有 22 种选择,现在我们的结论是走最远的最优。

    那么,我们看他走近的

    都没路走了,只能还是走远端的那片叶子,所以相当于浪费了一片叶子。

    走远的

    还能走,那么我想用这个例子说明什么呢?

    我们走得越远,选择越多。

    从贪心的角度来讲,要让所有魂师消耗的叶子数量尽量少。

    二分

    利用刚刚所讲的性质,我们用二分来写。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    template<typename T>inline void writen(T x){
    	write(x);
    	puts("");
    }
    int l,r=1,a[100010],b[100010],L,n;//左闭右开,r=1
    bool check(int mid){
    	memset(b,0,sizeof(b));//a[i]表示的是每个格子的上限,b[i]表示的是每个格子现有的数量
    	b[0]=mid;a[n]=mid;
    	for(int i=0;i<n;i++){
    		for(int j=min(i+L,n);j>=i+1;j--)//从远的开始试
    			if(b[j]<a[j]){
    				if(b[j]+b[i]<=a[j]){//全部都能去,那么就全部都去
    					b[j]+=b[i];//移走
    					b[i]=0;//变成零
    					break;
    				}else{
    					b[i]-=a[j]-b[j];//能塞,尽量塞
    					b[j]=a[j];//塞满
    				}
    			}
    		if(b[i]!=0)return false;//有人没去处,就代表不可能
    	}return true;//可能
    }
    int main(){
    	read(n);read(L);
    	for(int i=1;i<n;i++){
    		read(a[i]);
    		r+=a[i];
    	}
    	while(l+1<r){
    		int mid=(l+r)>>1;
    		if(check(mid))l=mid;
    		else r=mid;
    	}cout<<l;
    	return 0;
    }
    

    贪心

    我们发现,上面的二分似乎没什么用,知道答案也未必更好算。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    template<typename T>inline void writen(T x){
    	write(x);
    	puts("");
    }
    int a[100010],b[100010],L,n,s;
    int main(){
    	read(n);read(L);
    	for(int i=1;i<n;i++){
    		read(a[i]);
    		s+=a[i];//一样的道理
    	}
    	b[0]=s;a[n]=s;//拿边界
    	for(int i=0;i<n;i++){
    		for(int j=min(i+L,n);j>=i+1;j--)//从远的开始试
    			if(b[j]<a[j]){
    				if(b[j]+b[i]<=a[j]){//全部都能去,那么就全部都去
    					b[j]+=b[i];//移走
    					b[i]=0;//变成零
    					break;
    				}else{
    					b[i]-=a[j]-b[j];//能塞,尽量塞
    					b[j]=a[j];//塞满
    				}
    			}
    	}cout<<b[n];
    	return 0;
    }
    
  • 相关阅读:
    Twitter OA prepare: Rational Sum
    Java: Best Way to read a file
    Summary: gcd最大公约数、lcm最小公倍数算法
    Twitter OA prepare: Flipping a bit
    Twitter OA prepare: Equilibrium index of an array
    echo -e 参数
    openwrt 添加luci选项
    基于TLS的EAP 认证方法
    linux命令 dirname
    freeradius 错误: error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12817030.html
Copyright © 2011-2022 走看看