1. 程式人生 > >【2018-12-02模擬賽】T3 約束排列 解題報告

【2018-12-02模擬賽】T3 約束排列 解題報告

3.約束排列(place.pas/cpp/in/out)

問題描述:

給出 n 個互不相同的小寫字母,表示出現的字元型別,以及 k 個約束關係: .....,表示 ai 必須出現在 bi 前面(ai,bi 不會超出所給字元型別的範圍,且
ai!=bi)。
請按照字典序輸出所有滿足約束條件的序列。
如:
n=3,字元型別為:x y z
k=1,約束條件為:x z,表示 x 必須出現在 z 的前面。
所有滿足約束條件的排列有:
xyz
xzy
yxz

輸入:

第 1 行,2 個整數 n 和 k。
第 2 行,n 個空格隔開的字元。
接下來 k 行,每行二個字元 ai 和 bi(表示約束關係),資料保證不會出現矛盾的關係。

輸出:

若干行,每行 n 個字元(字元之間沒有空格),表示排列的結果。

樣例輸入:

3 1
x y z
x z

樣例輸出:

xyz
xzy
yxz

資料範圍:

對於 100%的資料:1<n<9,1≤k≤8。


思路

資料真的小,直接全排列,列舉即可。

對於檢查是否滿足K個約束,直接列舉,對於每個約束,如果先出現"應該先出現的"那就滿足要求,如果先出現“應該後出現的”,那就不滿足,標記之後再退出。

滿足所有約束的就輸出。

next_permutation( a + 1, a + n + 1 ):轉為下一個全排列,沒有了就返回0

(真搞不懂這種題目為嘛放T3???逗我麼??估計普及-。。。)

程式碼

#include<bits/stdc++.h>
using namespace std;

int N, K;
char s[20];
char a[20], b[20];

inline char Get(){
    char ans; while( ( ans = getchar() ) < 'a' || ans > 'z' );
    return ans;
}

int main(){
    freopen( "place.in", "r", stdin );
    freopen( "place.out", "w", stdout );
    scanf( "%d%d", &N, &K );
    for ( int i = 1; i <= N; ++i ) s[i] = Get();
    for ( int i = 1; i <= K; ++i ) a[i] = Get(), b[i] = Get();
    sort( s + 1, s + N + 1 ); s[N + 1] = '\0';
    do{
        bool flg(1);
        for ( int i = 1; i <= K; ++i )
            for ( int j = 1; j <= N; ++j ){
                if ( s[j] == a[i] ) break;
                if ( s[j] == b[i] ){ flg = 0; break; }
            }
        if ( flg ) printf( "%s\n", s + 1 );
    }while( next_permutation( s + 1, s + N + 1 ) );
    return 0;
}