Gym101666K. King of the Waves(DFS)

版权声明:Amove? https://blog.csdn.net/Amovement/article/details/88775608

                                                                                  K King of the Waves
Picture by JD Lasica via Flickr.
You are organising a king of the hill tournament, the Buenos Aires
Paddleboarding Competition (BAPC), with n participants. In a
king of the hill tournament, one person starts as a “king” and is
then challenged by another person, the winning person becomes
the new king. This is repeated until all participants have challenged exactly once (except for the starting person). In a paddleboarding match, there are no draws. The person which ends up as
king, wins the tournament. Since you are the organiser, you get to
choose the starting person and the order in which they challenge
the king.
Someone is offering you a substantial amount of money in case
one of the participants, Henk, ends up winning the tournament. You happen to know, for
any two participants x and y, which of the two would win if they were to match during the
tournament. Consequently, you choose to do the unethical: you will try to rig the game. Can
you find a schedule that makes Henk win the tournament?
Input
• The first line contains an integer 1 ≤ n ≤ 1000, the number of participants. The
participants are numbered 0, . . . , n − 1, where Henk is 0.
• Then n lines follow, where each line has exactly n characters (not counting the newline
character). These lines represent the matrix with the information of who beats who, as
follows. On line i the jth character is (note that 0 ≤ i, j < n):
– ’1’ if person i will win against person j.
– ’0’ if person i will lose against person j.
– ’X’ if i = j.
Output
Print a sequence of participants, such that the first person starts as king and the consequent
participants challenge the king. If there is no way to rig the game such that Henk wins, print
“impossible”.


Sample Input 1
3
X10
0X1
10X

Sample Output 1
1 2 0

Sample Input 2

3
X10
0X0
11X

Sample Output 2
impossible

一、原题地址

点我传送

二、大致题意

给出一个n*n的矩阵关系:

1-表示第i号选手能击败第j号选手;

0-表示第i号选手不能击败第j号选手;

X-表示自己和自己的胜负是没有意义的。

选手之间按照你规定的顺序依次进行比赛,获胜的人留下来守擂,一直到他被打败下一个选手成为擂主,或是他一直赢下去然后成为最后的擂主。

询问就是让你设计这个挑战的顺序,来保证0号选手成为最后的擂主。

 


三、大致思路

     一开始是想到了建立( u , v )的边表示u能打败v然后去依次以每个选手为起点跑深搜,看是否有可行解,但是这样的复杂度就达到了阶乘的规模,所以就想着优化。后来脑补到从0号选手出发,每到一个点就打上标记往下跑,看他能否跑出n个点的深度,如果不行就回溯取消标记再跑,但是这样的复杂度差不多是n^3想想又不行。

     正解是看到了官方题解里面的分析,先建立(u,v)的边是没有问题的,从0开始往下面跑也是没有问题的,但是问题就在于回溯时标记的取消,从0开始按照胜利的边往下跑是没有问题的(一旦找到可行就反向输出就行),关键在于回溯时当前跑过的点的标记是不需要取消的,这样做为什么是正确的呢?

    可以这样思考这样的例子: 0能击败x,x能击败y和z,但是z却可以击败0,那么把z放在0后面是否合理?

我们在DFS序中,y和z肯定是在x之后的,也就是说当DFS跑到x时,我们当前规定的擂主是x,他能击败y和z,也就是说往下的搜索不会影响到x擂主的身份,我们需要保证的仅仅是0能击败x就足够了。

具体的例子就像下图跑搜索:

按照顺序从0->1  ,1加入答案。

然后顺序从1->2  ,2加入答案。

2无处可去回溯到1.

然后顺序从1->3  ,3加入答案。

此时3虽然是可以击败0 的,但是他的顺序是在1之后,也就是说此时守擂的人仍然是1,所以真实的并不是3去挑战的0。

即使图上的关系再怎么复杂,按照这个思路进行下去仍然是一种符合条件的。

那么他的反面——是不是只要跑不出n个点就表示是不可能的呢?这是正确的吗。怎么理解,我是这样想的,就好比0在第一步就无法向下了,那么就代表了0无论向谁挑战都不能成为擂主,或者谁向0挑战都可以胜利之,所以0安排在任意位置都不行。这也可以推广到在第1步无法向下了、第2步无法向下、第3、第4……第n-1,只不过是把点0扩张成了一段的比赛关系,但是实质还是0为擂主,谁向0挑战都可以胜利之,他也无法胜利除这一段以外的任意人,那么这一段关系也就无法放在答案的任意位置,所以之前的想法是正确的。


四、代码

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include<set>
#include<map>
#include<queue>
#include<string>
#include<stack>
using namespace std;
const double eps = 1e-6;
typedef long long LL;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
const int inf=0x3f3f3f3f;
const LL INF=0x3f3f3f3f3f3f3f3f;

const int maxn=1005;
int n;
int G[maxn][maxn];
vector<int>ans;
bool tag,vis[maxn];

void read()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        char s[maxn];scanf("%s",s);
        for(int j=0;j<n;j++)
        {
            if(s[j]=='X'||s[j]=='0')G[i][j]=0;
            else if(s[j]=='1')G[i][j]=1;
        }
    }
    return ;
}

void DFS(int nx)
{
    ans.push_back(nx);
    if(ans.size()==n)
    {
        tag=true;
        return ;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[i]&&G[nx][i])
        {
            vis[i]=true;
            DFS(i);
        }
    }
    return ;
}

int main()
{
    read();
    tag=false;
    vis[0]=true;DFS(0);
    if(!tag)printf("impossible\n");
    else
    {
        for(int i=ans.size()-1;i>=0;i--)
        {
            printf("%d",ans[i]);
            if(i!=0)printf(" ");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Amovement/article/details/88775608
今日推荐