• [luogu]P1073:最优贸易


    原题链接

    最优贸易

    分析

    先分析题意:
    给定一张图,点序号为1-n,你从1点开始旅游,到n点结束旅途。每个点都有卖水晶球(雾),你可以在旅途中买水晶球并在另一个地方卖出,该操作最多进行一次,求最大收益。

    暴搜+剪枝+玄学dp
    考虑暴搜,暴力搜索每一种走法(可往返),但是这样子程序肯定停不下来,因为可以重复走,需要加入边界使程序停下来。
    类似于SPFA的思想,对每个dp状态以及路径最小值进行松弛(差不多理解下)。

    • 如果松弛成功的话,不回跳。
    • 如果松弛失败,跳出dfs。

    dp方程:f[i]表示以i点为终点最大收益。
    f[i]=max(f[fa],val[i]-minn)
    其中fa为i的父节点,val[i]为i点出售的水晶球价格,minn为路径最小价格。
    当结束dfs时,f[n]即为答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100009,M=500009;
    int read(){
    	char c;int num;
    	while(c=getchar(),!isdigit(c));num=c-'0';
    	while(c=getchar(), isdigit(c)) num=num*10+c-'0';
    	return num;
    }
    int n,m,val[N],dp[N],kk[N];
    int head[N],nxt[M*2],ver[M],tot=1;
    void dfs(int x,int minn,int fa);
    int main()
    {
    	int x,y,f;
    	n=read();m=read();
    	memset(kk,0x3f,sizeof(kk));
    	for(int i=1;i<=n;i++)
            val[i]=read();
    	for(int i=1;i<=m;i++){
    		x=read();y=read();f=read();
    		ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;
    		if(f==2){
    			ver[++tot]=x;nxt[tot]=head[y];head[y]=tot;
    		}
    	}
    	dfs(1,1<<31-1,0);
    	printf("%d
    ",dp[n]);
    	return 0;
    }
    void dfs(int x,int minn,int fa){
    	bool f=1;
    	minn=min(val[x],minn);
    	if(kk[x]>minn){
    		kk[x]=minn;
    		f=0;
    	}
    	int maxn=max(dp[fa],val[x]-minn);
    	if(dp[x]<maxn){
    		dp[x]=maxn;
    		f=0;
    	}
    	if(f)return ;
    	for(int i=head[x];i;i=nxt[i])
    		dfs(ver[i],minn,x);
    	return ;
    }
    
    
    
    
  • 相关阅读:
    Linux下校验下载文件的完整性(MD5,SHA1,PGP)
    十六进制字节 & 十六进制转二进制
    session & cookie
    php与mysql的链接到底用mysql 还是mysqli,pdo
    php连接数据库时候的字符集设置
    Prepared statements(mysqli & pdo)
    shell脚本中执行mysql命令
    centos系统字符编码问题
    实用crontab命令
    shell获取用户输入
  • 原文地址:https://www.cnblogs.com/onglublog/p/9859727.html
Copyright © 2020-2023  润新知