zoukankan      html  css  js  c++  java
  • [CF1101F]Trucks and Cities:分治优化决策单调性

    分析

    好像是有一个叫这个名字的算法,链接

    (f[i][j][k])表示一辆每公里耗油量为(1)的货车从(i)(j)中途加(k)次油最小的油箱容量。枚举所有的起点和中途加油的次数,这样就固定了两维,显然有DP方程:

    [f[i][j][k]= min_{p=i}^{j} ( max (f[i][p][k-1],a[j]-a[p])) ]

    根据生活经验题意显然这个DP具有决策单调性,可以用分治优化一下。

    具体来说就是每次大力求出(mid=(l+r)/2)的决策点,然后分治就好了,显然分治左区间的决策点一定不在(mid)的决策点(这里一定要注意是(mid)的决策点而不是(mid))的右边,分治右区间的决策点一定不在(mid)的决策点的左边。

    代码

    #include <bits/stdc++.h>
    #define rin(i,a,b) for(register int i=(a);i<=(b);++i)
    #define irin(i,a,b) for(register int i=(a);i>=(b);--i)
    #define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=405;
    int n,m,a[MAXN],f[MAXN][MAXN][MAXN];
    
    void solve(int bg,int cnt,int l,int r,int ql,int qr){
    	if(l>r) return;
    	int mid=((l+r)>>1),opt=0,temp=0;
    	rin(i,ql,std::min(qr,mid))
    		if(!opt||std::max(a[mid]-a[i],f[bg][i][cnt-1])<temp)
    			temp=std::max(a[mid]-a[i],f[bg][i][cnt-1]),opt=i;
    	f[bg][mid][cnt]=temp;
    	solve(bg,cnt,l,mid-1,ql,opt);
    	solve(bg,cnt,mid+1,r,opt,qr);
    }
    
    int main(){
    	n=read(),m=read();
    	rin(i,1,n) a[i]=read();
    	rin(i,1,n) rin(j,i,n) f[i][j][0]=a[j]-a[i];
    	rin(i,1,n) rin(j,1,n) solve(i,j,i+1,n,i+1,n);
    	LL ans=0;
    	rin(i,1,m){
    		int s=read(),t=read(),c=read(),r=read();
    		ans=std::max(ans,1ll*f[s][t][r]*c);
    	}
    	printf("%I64d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    FTP-实例(Md5验证)
    Socket-实例
    函数对象、函数嵌套、名称空间与作用域、装饰器
    Docker——手动创建镜像
    Docker——桥接网络配置
    Docker——网络和存储(数据卷)
    Docker-PS命令解析
    面试题44:扑克牌的顺子
    面试题42:翻转单词顺序VS左旋转字符串
    面试题41:和为s的两个数字VS和为s的连续正数序列
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10260195.html
Copyright © 2011-2022 走看看