P1294 高手去散步

写在最前

在经历大一的一年学习后,发现卷课内绩点去保研并不适合我,在前两个学期的课内学习时间花得挺多的,最后出来的大一均绩3.1上下,目前在专业里排50%,但在大二大类分流之后会更加落后,索性及时改变方向。
家里的条件和个人原因我不适合出国,目前摆在面前的就是考研和就业两条路。考研网上都说是大三开始努力,为期一年,所以在现在就以考研为目标显然是不理智的,大二一年的时光不能被虚度,所以目前的打算安排就是 “尽可能” 兼顾二者作出的决定:
学好三大件:数据结构、计算机网络、操作系统 ; 学好英语:通过国外课程CS61B(正在进行) CS61C(未来) ;学好算法:去年一年断断续续地学,蓝桥杯拿了省二,今年再接再厉,争取进个国赛。

题目背景

高手最近谈恋爱了。不过是单相思。“即使是单相思,也是完整的爱情”,高手从未放弃对它的追求。今天,这个阳光明媚的早晨,太阳从西边缓缓升起。于是它找到高手,希望在晨读开始之前和高手一起在鳌头山上一起散步。高手当然不会放弃这次梦寐以求的机会,他已经准备好了一切。

题目描述

鳌头山上有 n n n 个观景点,观景点两两之间有游步道共 m m m 条。高手的那个它,不喜欢太刺激的过程,因此那些没有路的观景点高手是不会选择去的。另外,她也不喜欢去同一个观景点一次以上。而高手想让他们在一起的路程最长(观景时它不会理高手),已知高手的穿梭机可以让他们在任意一个观景点出发,也在任意一个观景点结束。

输入格式

第一行,两个用空格隔开的整数 n n n m . m. m. 之后 m m m 行,为每条游步道的信息:两端观景点编号、长度。

输出格式

一个整数,表示他们最长相伴的路程。

样例

样例输入

4 6
1 2 10
2 3 20
3 4 30
4 1 40
1 3 50
2 4 60

样例输出

150

提示

对于 100 % 100\% 100% 的数据: n ≤ 20 n \le 20 n20 m ≤ 50 m \le 50 m50,保证观景点两两之间不会有多条游步道连接。

开始思路

本题是在洛谷dfs中找的橙题,看上去比较人畜无害的模板题,通过book[ ]来记录每个景点有没有走过,把上一次结束的点last作为当前的起点去搜索,通过全局变量sum来记录路程。

初始代码

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;

const int N=20+5;
int n,m,a[N],b[N],len[N],sum,ans;
bool book[N];

void dfs(int last){
	bool judge=0;
	for(int i=0;i<n;i++){
		if(!book[i]){
			judge=1;
			break;
		}
	}
	if(!judge){
		ans=max(ans,sum);
		return;
	}
	ans=max(ans,sum);
	for(int i=0;i<m;i++){
		if(!book[i]&&a[i]==last){
			sum+=len[i];
			book[i]=1;
			dfs(b[i]);
			book[i]=0;
			sum-=len[i];
		}
	}
	return;
}

signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	
	cin>>n>>m;
	for(int i=0;i<m;i++) cin>>a[i]>>b[i]>>len[i];
	for(int i=0;i<n;i++){
		book[i]=1;
		dfs(i);
	}
	cout<<ans;
	
	return 0;
}

反思

不能正确输出。本题不需要传统dfs的判断结束,因为如果没有空闲的点,那么自然就结束了;在主函数中的每次dfs(i)都要重置book[ ]数组,以免对下一次的dfs造成影响;本题是图,如果按现在做法,只能判断正向方向,因为每次都在a[ ]中找上次的last,所以要开二维数组存图

AC代码

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;

const int N = 20 + 5;
int n, m, a[N][N], ans;
bool book[N];

void dfs(int last, int sum) {	//把全局变量sum改为了dfs的参数
   ans = max(ans, sum);
    for (int i = 1; i <= n; i++) {
        if (!book[i] && a[last][i]) {	//a[last][i]确保有这条路线,防止走成死胡同
            book[i] = 1;
            dfs(i, sum + a[last][i]);
            book[i] = 0;	//回溯
        }
    }
    return;
}

signed main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	//输入输出优化(算法竞赛必备)
    
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        a[x][y] = z;	//二维数组存图
        a[y][x] = z;
    }
    for (int i = 1; i <= n; i++) {
        book[i] = 1;
        dfs(i, 0);
        memset(book, 0, sizeof(book));	//重置book[]数组
    }
    cout << ans;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Achilles0705.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值