DFS+剪枝
思路:
(1)题目要求按照字典序最小的顺序输出,那么第一个数字必然是1
证明(反证法):如果第一个数字不能是1,说明1没有战胜过任何队伍
那么将1填入到食物链当中,必然有一个环节不符合条件(1没有后继)
所以没有任何一种序列符合条件(2)我们dfs从小到大搜索答案,重点在于剪枝
剪枝主要有两种情况
1.已经搜索到答案
已经搜索到答案有两种情况
(1)当前dfs搜索到答案,直接返回
(2)因为除了当前dfs,栈中还会有其他的许多dfs,这时候就会出现一种情况
当前dfs已经搜索到答案,返回。但是之后还没有执行完的dfs又搜索出了答案
那么之后搜索的出的答案就会更新之前搜索到的答案,又因为我们是按字典序搜索的
所以之后的答案字典序肯定更大,答案就会出错
所以我们要增加一个判断:当答案已经搜索到了,可以是自己也可以是被人搜索到的
那么久返回。
2.答案不存在
如果没有队伍战胜过1号队伍,那么答案肯定不存在
因为最后一个队伍与对头1无法构成食物链
AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 110;
int n;
bool w[N][N], st[N];
vector<int> res, path;
bool check()
{
for(int i = 1; i <= n; i ++)
if(!st[i] && w[i][1])
return true;
return false;
}
void dfs(int u, vector<int> path)
{
//剪枝1.1
if(path.size() == n - 1)
{
res = path;
return ;
}
//剪枝1.2
if(res.size()) return ;
//剪枝2
//该无答案判断需要放在判断有答案的前面
//因为当答案搜索出来的时候,check一定会返回false
if(!check()) return ;
for(int i = 1; i <= n; i ++ )
{
if(!st[i] && w[u][i])
{
st[i] = true;
path.push_back(i);
dfs(i, path);
path.pop_back();
st[i] = false;
}
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++ )
{
string s; cin >> s;
for(int j = 0; j < s.length(); j ++ )
{
if(s[j] == 'W') w[i][j + 1] = 1;
else if(s[j] == 'L') w[j + 1][i] = 1;
}
}
st[1] = true;
dfs(1, path);
if(!res.size()) puts("No Solution");
else
{
cout << 1 << " ";
for(int i = 0; i < res.size(); i ++ )
{
cout << res[i];
if(i != res.size() - 1) cout << ' ';
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】