题目
题目链接**
背景
我必须得吐槽一波这题,昨天一直没有思路,是因为我理解有误(还是题目描述不清),我把这个想复杂了,我给想成类似于一个图,然后可以来来回回走,但是,实际上就是一条路径直接走到底,不走回头的。这样就太简单了,之前我想的那种,只要是某一个房间和其他房间之一都不是断开的,然后就可以走来走去,很可能把所有房间都走遍了,这样也就无所谓最大值呃。
说来离了个大谱,昨晚(准确来说是今晚)我没睡着,就躺在那,反正也没事干我在想这个题目,我想了一种回溯的方法(我按照那个理解错的方式想的思路,当然不行),然后又想是不是只可以一条路径走下去(😢bingo了),然后早晨爬起来就写了,发现回溯还是不对,然后直接换第二种想法,把最大值搞定了,然后参考题解把路径解决,没想到真的
AC了😄,修改全程5分钟,昨晚搞了1小时,福乐。
思路
本题类似于昨天做的滑雪题,我暂时感觉是差不多的,只是在哪里能走上有区别
滑雪题要判断上下左右四个方向哪些能走哪些不能走,这个则要判断根据连接矩阵判断哪里可以走
又因为滑雪题是dp初始化为1,然后每次都是加1,和这题有所不同,但是这题又和最大数字路径和很像
于是可以模仿这两道题目进行解答
代码
#include<iostream>
#include<algorithm>
using namespace std;
int n;
long long a[22];
long long dp[22]={0};
int connect[22][22];
int p[22],pos;
void DFS(int x){
if(p[x]==0) return;
if(p[x]) cout<<p[x]<<' ';
DFS(p[x]);
}
long long func(int m){//第m个地窖
if(dp[m])
return dp[m];//如果已经有了dp值,就直接返回
dp[m]=a[m];
int i;
for(i=m+1;i<=n;i++){
if(connect[m][i]){
func(i);
if(a[m]+dp[i]>=dp[m]){
dp[m]=a[m]+dp[i];
p[m]=i;
}
}
}
return dp[m];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n-1;i++){
for(int j=i+1;j<=n;j++){
cin>>connect[i][j];
}
}
long long ans=0;
for(int i=1;i<=n;i++){
if(func(i)>ans){
ans=func(i);
pos=i;
}
}
cout<<pos<<" ";
DFS(pos);
cout<<endl;
cout<<ans;
return 0;
}
复盘
dp的过程很简单,不需要记录了
主要这两个点我还是记住
第一点:dp[m]=a[m]
这个语句一开始忘了,这个是类似滑雪的,如果不加这个语句,那么到最后那个房间的时候
会直接return dp数组,而dp数组初始化值都是0,所以你就少加了最后一个的值
第二点:那个DFS的过程,
其实我写的应该不是DFS,这个知识点还是要学一下的,其实理解起来也不难啊,
就是我记录每次进去的第m个房间的后缀(能使dp最大的后缀)
然后我再记录一下刚开始从哪个房间开始,就是最外循环,然后跟一个静态链表一样,直接一点点访问即可。