1 条题解

  • 0
    @ 2025-8-24 22:16:26

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 奇米
    **

    搬运于2025-08-24 22:16:26,当前版本为作者最后更新于2020-01-26 09:04:11,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题解-P6005 Time is Mooney G

    • 题目意思

    就是给你一个有向图,你在上面走,没经过一个点可以获得mim_i,最后你要减去sum2sum^2(走过的边数)C*C

    • SolSol

    考虑DPDP,我们设fi,jf_{i,j}表示第ii天到达城市jj的最大收益。

    转移很简单fi,j=max{fi1,lasj+mj,fi,j}f_{i,j}=max\{f_{i-1,las_j}+m_j,f_{i,j}\}

    对于lasjlas_j的处理我们只需要反向建有向边即可,答案就是max{fi,1i2C}max\{f_{i,1}-i^2*C\}

    但是这样ii的枚举范围无法确定,但是我们发现i1000i\leq 1000即可,因为max{mi}dayday2C1max\{m_i\}*day-day^2*C\leq 1

    • CodeCode
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1005;
    
    int n,m,C,cnt,head[N];
    int M[N],f[N][N],ans; 
    
    struct nood {
    	int nex,to;
    };
    nood e[N<<2];
    
    inline void jia(int u,int v) {
    	e[++cnt].nex=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    
    inline int read() {
    	int sum=0; char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) 
    		sum=sum*10+(ch^48),ch=getchar();
    	return sum;
    }
    
    int main() {
    	n=read();
    	m=read();
    	C=read();
    	for ( int i=1;i<=n;i++ ) M[i]=read();
    	for ( int i=1;i<=m;i++ ) {
    		int u,v;
    		u=read();
    		v=read();
    		jia(v,u);
    	}
    	//f[i][j]表示第i天到达第j座城市的最大收益
    	memset(f,-1,sizeof(f));
    	f[0][1]=0;
    	for ( int i=1;i<=1000;i++ ) {
    		for ( int j=1;j<=n;j++ )
    			for ( int k=head[j];k;k=e[k].nex ) {
    				int v=e[k].to;
    				if(~f[i-1][v]) 
    					f[i][j]=max(f[i][j],f[i-1][v]+M[j]);
    			}
    		if(ans<f[i][1]-C*i*i) ans=f[i][1]-C*i*i;
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    	
    
    • 1

    信息

    ID
    5021
    时间
    2000ms
    内存
    250MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者