• $HNOI2005$星际贸易


    因为【数据删除】俺懒得写有趣的链接了

    (TM)的超多信息。。。

    认真观察一波题面,我们发现第一问就是个背包,跑一遍就好了。

    状态为(f[i][j])表示前(i)个星球,卖了(j)吨的最大贸易额。

    但是在第一问中的最优答案和第二问有关,具体来说是第一问中的中转移的点必选。

    关于第二问,我们设(f[i][j])表示到第(i)个星球,剩余(j)个燃料的最小花费。

    根据买燃料和维修两种情况转移就好了。

    (f[i][j]=max(f[i][j-1]+P_i,f[k][j+2]+F_i))

    显然这个转移是(n^3)的,我们通过(yyb)的博客发现有单调性,用单调队列维护即可。

    注意遇到第一问中必须转移的点时队列清空。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int N=2e3+10;
    int n,MF,ML,m,J,JJ,Q[N<<1][N];
    int f[N][N<<1],Vis[N<<1],H[N<<1],T[N<<1];
    struct Planet
    {
    	int Out,Mon;
    	int Dis,Amt,Fix;
    } p[N];
    signed main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	n=read();m=read(),MF=read(),ML=read();
    	if(MF>(n<<1)) MF=n<<1;
    	for(int i=1;i<=n;i++)
    	{
    		p[i].Out=read(),p[i].Mon=read();
    		p[i].Dis=read(),p[i].Amt=read(),p[i].Fix=read();
    	}
    	for(int i=1;i<=n;i++)
    		if(p[i].Dis-p[i-1].Dis>ML){puts("Poor Coke!");return 0;}
    	memset(f,0xf3,sizeof(f));f[0][0]=0;
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<=m;j++)
    		{
    			if(j>=p[i].Out)
    				f[i][j]=max(f[i-1][j],f[i-1][j-p[i].Out]+p[i].Mon);
    			f[i][j]=max(f[i-1][j],f[i][j]);
    		}
    	for(int i=1;i<=m;i++) if(f[n][i]>f[n][J]) J=i;
    	int MYE=f[n][J];
    	for(int i=n,Now=J;i;i--)
    		if(f[i][Now]!=f[i-1][Now])
    			Vis[i]=1,Now-=p[i].Out;
    	memset(f,0x3f,sizeof(f));
    	f[0][MF]=0;Q[MF][T[MF]++]=0;
    	//H[MF]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<=MF;j++)
    		{
    			if(p[i].Amt&&j) f[i][j]=min(f[i][j],f[i][j-1]+p[i].Amt);
    			if(T[j+2]>H[j+2]) f[i][j]=min(f[i][j],f[Q[j+2][H[j+2]]][j+2]+p[i].Fix);
    			if(Vis[i]) H[j]=0,T[j]=0;
    			while(H[j]<T[j]&&f[Q[j][T[j]-1]][j]>=f[i][j]) T[j]--;
    			Q[j][T[j]++]=i;
    			while(H[j]<T[j]&&p[i+1].Dis-p[Q[j][H[j]]].Dis>ML) H[j]++;
    		}
    	for(int j=1;j<=MF;j++) if(f[n][j]<f[n][JJ]) JJ=j;
    	f[n][JJ]>=1e9?puts("Poor Coke!"):printf("%lld %lld",MYE,MYE-f[n][JJ]);
    }
    
  • 相关阅读:
    判断一个值是不是数字
    webpack起的项目怎么用手机访问?
    vue 父子组件数据双向绑定
    js取整
    封装加减乘除函数 解决JS 浮点数计算 Bug
    javascript笔记 (持续更新)
    ajax请求的原生js实现
    程序员の健康和效率装备列表,普通人也能参考
    Java static,final 基本概念
    Download EditPlus Text Editor
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11808915.html
Copyright © 2020-2023  润新知