CCCC L3-015. 球队“食物链”(dfs+剪枝)

题意:

某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。

联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T1 T2 ... TN },满足:球队T1战胜过球队T2,球队T2战胜过球队T3,……,球队T(N-1)战胜过球队TN,球队TN战胜过球队T1

现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。

注:排列{ a1 a2 ...aN }在字典序上小于排列{ b1 b2 ... bN },当且仅当存在整数K(1 <= K <= N),满足:aK < bK且对于任意小于K的正整数i,ai=bi

输入格式:

输入第一行给出一个整数N(2 <= N <= 20),为参赛球队数。随后N行,每行N个字符,给出了NxN的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:“W”表示球队i战胜球队j,“L”表示球队i负于球队j,“D”表示两队打平,“-”表示无效(当i=j时)。输入中无多余空格。

输出格式:

按题目要求找到“食物链”T1 T2 ... TN,将这N个数依次输出在一行上,数字间以1个空格分隔,行的首尾不得有多余空格。若不存在“食物链”,输出“No Solution”。

分析:

1、若能形成食物链,字典序最小的一定以1开头。所以从1开始搜。

2、剪枝:若剩下没选的点,都不能战胜球队1,则剪掉。

3、给出的联赛结果表不是对称的,即“W”表示球队i战胜球队j,“L”表示球队i负于球队j这两个都需要标记。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
    if(fabs(a - b) < eps) return 0;
    return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 20 + 10;
const int MAXT = 10000 + 10;
using namespace std;
char pic[MAXN][MAXN];
int a[MAXN][MAXN];
bool vis[MAXN];
int ans[MAXN];
int N;
bool ok;
void dfs(int cur, int now){
    if(ok) return;
    ans[now] = cur;
    if(now == N){
        if(a[cur][1]){
            ok = true;
        }
        return;
    }
    bool flag = false;
    for(int i = 1; i <= N; ++i){
        if(!vis[i] && a[i][1]){
            flag = true;
            break;
        }
    }
    if(!flag) return;
    for(int i = 1; i <= N; ++i){
        if(!vis[i] && a[cur][i]){
            vis[i] = true;
            dfs(i, now + 1);
            if(ok) return;
            vis[i] = false;
        }
    }
}
int main(){
    scanf("%d", &N);
    for(int i = 1; i <= N; ++i){
        scanf("%s", pic[i] + 1);
    }
    for(int i = 1; i <= N; ++i){
        for(int j = 1; j <= N; ++j){
            if(pic[i][j] == 'W'){
                a[i][j] = 1;
            }
            else if(pic[i][j] == 'L'){
                a[j][i] = 1;
            }
        }
    }
    vis[1] = true;
    dfs(1, 1);
    if(!ok){
        printf("No Solution\n");
        return 0;
    }
    for(int i = 1; i <= N; ++i){
        if(i != 1) printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
    return 0;
}

 

posted @ 2017-04-13 21:38  Somnuspoppy  阅读(349)  评论(0编辑  收藏  举报