1 条题解

  • 0
    @ 2025-8-24 21:28:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar WaterSky
    泠泠风自扬·澹澹夜未央

    搬运于2025-08-24 21:28:46,当前版本为作者最后更新于2023-04-18 23:14:20,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    题目传送门:P1759 通天之潜水。

    前言:

    这篇题解共分为两部分。

    Part 1:

    这是一道动态规划的题目,既然是动态规划,那么就要弄清楚状态,状态转移公式。

    从题目中可以看出,这是一道背包问题。那么既然知道了是背包问题,那么状态和状态转移公式就很容易得出了。首先是状态,对于 dp[i][j]dp[i][j],表示重量为 ii,阻力为 jj 的能够获得的最大价值。其次,就是状态转移公式,根据背包问题的公式,可以得出:

    dp[i][j]=max(dp[i][j],dp[im][jv]+w)dp[i][j]=\max(dp[i][j],dp[i-m][j-v]+w)

    其中,vv 代表这件物品的阻力,mm 代表这件物品的重量,ww 代表这件物品的价值。

    确定好状态和状态转移公式,还要确定怎么记录使用的工具有哪些。我使用的方法是用二维字符串数组来记录,当当前的最高价值要更新时,这个字符串数组的对应字符串也要跟着更新。

    弄清楚以上代码后,就可以轻松的打出代码来:

    #include <bits/stdc++.h>//万能头文件。
    using namespace std;
    long long n,m,v,dp[1005][1005];//定义背包数组。
    string ans[1005][1005];//定义字符串二维数组。
    struct wbx{
    	long long a,b,c;
    }a[1005];//每一个工具都用结构体记录。
    int main(){
    	cin>>m>>v>>n;//输入变量。
    	for(int i=1;i<=n;i++) cin>>a[i].a>>a[i].b>>a[i].c;//输入每一个工具对应的数值。
    	for(int i=1;i<=n;i++)
    		for(int j=m;j>=a[i].a;j--)
    			for(int k=v;k>=a[i].b;k--)
                			//如果用现在可以的阻力和重量分别减少这个工具所产生的价值大于原来的价值,
                            	那么就应该更新这个最大价值。
    				if(dp[j-a[i].a][k-a[i].b]+a[i].c>dp[j][k])
    					dp[j][k]=dp[j-a[i].a][k-a[i].b]+a[i].c,ans[j][k]=ans[j-a[i].a][k-a[i].b]+char(i);
                        		//状态转移公式
    	cout<<dp[m][v]<<endl;//输出最大价值。
    	for(int i=0;i<ans[m][v].size();i++) cout<<int(ans[m][v][i])<<" ";//输出答案。
    	return 0;
    }
    

    Part 2:

    但是在添加了 能够 Hack 掉所有题解的数据,怎么可能这么容易让你对?

    我一开始也是被 Hack 掉了,在仔细的读题之后,发现,我一直都省略掉了一句话:若有多种方案,输出前面尽量小的方案。

    在讨论版找到了 Hack 数据后,我发现我就是错了这一个地方。 那么要怎么办呢?可以在判断条件中加入一个:如果价值相等,那么就挑选字典序更小的那一个。这样子,就可以 AC 了。

    #include <bits/stdc++.h>//这个程序在上面有对应的注释。
    using namespace std;
    long long n,m,v,dp[1005][1005];
    string ans[1005][1005];
    struct wbx{
    	long long a,b,c,t;
    }a[1005];
    int main(){
    	cin>>m>>v>>n;
    	for(int i=1;i<=n;i++) cin>>a[i].a>>a[i].b>>a[i].c,a[i].t=i;
    	for(int i=1;i<=n;i++)
    		for(int j=m;j>=a[i].a;j--)
    			for(int k=v;k>=a[i].b;k--)
    			{
    				if(dp[j-a[i].a][k-a[i].b]+a[i].c>dp[j][k] || dp[j-a[i].a][k-a[i].b]+a[i].c==dp[j][k] && ans[j-a[i].a][k-a[i].b]+char(a[i].t)<ans[j][k])
    				dp[j][k]=dp[j-a[i].a][k-a[i].b]+a[i].c,ans[j][k]=ans[j-a[i].a][k-a[i].b]+char(a[i].t);
    			}
    				
    	cout<<dp[m][v]<<endl;
    	for(int i=0;i<ans[m][v].size();i++) cout<<int(ans[m][v][i])<<" ";
    	return 0;
    }
    	return 0;
    }
    

    谢谢!

    • 1

    信息

    ID
    733
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者