PAT-L3-球队“食物链”-dfs-状压-set

时间:2024-04-27 22:36:59

题目分析:

1. 一场双循环赛制的篮球赛,注意双循环,双循环!

2. 共有n只球队,两两之间有胜有负有平局;

3. 输入:

举例:

第一行:W:代表球队1打赢这只队伍

L:代表球队2没打赢这只队伍

因为两队伍有两场比赛,所以互相都可能打败对方;

如果A队打赢过B队,就连一条A到B的有向边;

建边时注意,如果A队 "L" B队,就连一条B->A边;(忘了这个wa了一发)

(这是坑点1,不是最可怕的)

4. 目的:

找到一条食物链:1 3 5 4 2;

代表:1赢过3,3赢过5,5赢过4,4赢过2,并且 2赢过1

要循环的;

解题思路:

1. 很明显dfs可以解决;如果A队打赢过B队,就连一条A到B的有向边;

(因为我很傻以为球队有很多只,怕超时,sb的用set写,其实这个二维数组建边就行了,不过两种写法差别不大,我就当作 是温习一下set的知识。结果被set一个坑点卡了一晚上,贼气,我在结尾说这个蛋疼的故事)

2. 减枝:状压一下吧(应该是叫状压吧?唉,我太菜了)

state[cur][i]表示状态cur的最后一步是i;

如果为1,代表这个不可行,continue掉;

题目链接:https://www.patest.cn/contests/gplt/L3-015

(怎么弄超链接,我真的不会)

AC代码如下:

#include<bits/stdc++.h>
#define test printf("***\n")
#define ka getchar();getchar()
#define ka1 getchar()
using namespace std;
typedef long long LL;
const int N = ;
const int M = ;
const int INF = 0x3f3f3f3f;
const LL mod = ;
const double eps=1e-;
int vis[N],ans[N];
int state[<<][N];//坑点1,状压处理
set<int> son[N];
char ar[N][N];
int flag,n;
void dfs(int u,int t,int cur){
if(flag)return;
for(set<int>::iterator p=son[u].begin();p!=son[u].end();++p){
int tmp=*p;
if(t==n){
if(tmp==ans[]){
flag=;
return;
}
continue;
}
if(vis[tmp]||state[cur|(<<tmp)][tmp])continue;
vis[tmp]=;
ans[t]=tmp;
dfs(tmp,t+,cur|(<<tmp));
if(flag)return;
state[cur|(<<tmp)][tmp]=;
vis[tmp]=;
}
}
int main(){
flag=;
scanf("%d",&n);
for(int i=;i<=n;++i){
son[i].clear();
}
for(int i=;i<n;++i){
scanf("%s",ar[i]);
for(int j=;j<n;++j){
if(ar[i][j]=='W'){
son[i].insert(j);
}
if(ar[i][j]=='L'){
son[j].insert(i);//坑点2,双循环赛制
}
}
}
memset(vis,,sizeof(vis));
vis[]=;
ans[]=;
dfs(,,);
if(flag==){
printf("No Solution\n");
return ;
}
for(int i=;i<n;++i){
if(i!=n-) printf("%d ",ans[i]+);
else printf("%d\n",ans[i]+);
}
return ;
}

(set遍历元素不是要先:set<int>::iterator 吗;然后我 set<int>::iterator p,把p作为全局变量,然后dfs找bug找一晚上,至于为什么不要设为全局变量,自己试一下就知道了)

(写完****再写博客园,真累)