P1854-DP【绿】

发布时间 2023-12-09 12:11:50作者: Kai-G

首先通过这道题我收获了一个知识,那就是deque可以直接赋值,作用和vector类似就是复制一个一摸一样的deque,很好用,越来越发现deque眉清目秀了起来。以后deque可能是我最常用的STL结构了。毕竟queue、stack都用deque来实现明显更方便而且不会多占用什么空间的。

一眼便能看出,这道题用记忆化搜索+动态申请空间应该能大大大大大地减少所用空间,应该还能减少时间,不过大体思路一想便知,而且记搜,本就是自己更熟悉的写法,便也就不写了。

这道题的状态转移不复杂,甚至记录最优解过程这本身也不复杂(由于数据范围过小,不用记搜+空间优化也能过所以才说记录最优解不难,但如果数据范围大一些逼迫我们选择记搜式的存储路径那才算是有些难度了)。这俩者加起来充其量是个黄+的难度,算不上是绿题。但是有一个小小的坑点,那就是非法情况应该排除,这个点不容易想到因此容易导致WA。加上这个点,这道题评个绿还是很公正的。

另外,总结一下排除非法情况的方法,那就是在dp存储最优解的过程中只要把非法情况设置为“可以采取但是效果极其极其差”即可,这样便能让程序发自内心的“可以选择但不选择”。而非直接强迫程序不准选择。这么做好处很明显,明显减少编码复杂度和思维复杂度和出bug的可能性。

#include <iostream>
#include <cstring>
#include <deque>
using namespace std;
int F,V,dp[105][105],a[105][105];
deque<int> q[105][105];
signed main()
{
	memset(dp,0,sizeof(dp));
	cin>>F>>V;
	for(int i=1;i<=F;i++)
		for(int j=1;j<=V;j++)
			cin>>a[i][j];
	for(int i=1;i<=F;i++)dp[i][0]=-99999999;
	for(int i=1;i<=F;i++)
	{
		for(int j=1;j<=V;j++)
		{
			if(i>j)dp[i][j]=-99999999;
			else if(dp[i-1][j-1]+a[i][j]>=dp[i][j-1])
			{
				dp[i][j]=dp[i-1][j-1]+a[i][j];
				q[i][j]=q[i-1][j-1];
				q[i][j].push_back(j);
			}
			else
			{
				dp[i][j]=dp[i][j-1];
				q[i][j]=q[i][j-1];
			}
		}
	}
	cout<<dp[F][V]<<endl;
	for(auto p=q[F][V].begin();p!=q[F][V].end();p++)
		cout<<*p<<' ';
	return 0;
}