zoukankan      html  css  js  c++  java
  • 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
    ");
            return 0;
        }
        for(int i = 1; i <= N; ++i){
            if(i != 1) printf(" ");
            printf("%d", ans[i]);
        }
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    伟景行 citymaker 从入门到精通(2)——工程图层树加载
    伟景行 citymaker 从入门到精通系列
    伟景行 citymaker 从入门到精通(1)——js开发,最基本demo,加载cep工程文件
    Android手机屏幕投射到电脑神器Vysor
    GeoTools坐标转换(投影转换和仿射变换)
    微信开发系列(1):企业号回调模式认证
    通过扩大IE使用内存,解决skyline在IE下模型不能加载的方法
    SDE ST_Geometry SQL st_intersects查询很慢的解决方法
    axTE3DWindowEx双屏对比控件白屏解决方法以及网上方法的校正(CreateControlOveride)
    namespace使用方法
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/6706290.html
Copyright © 2011-2022 走看看