【2018-12-02模擬賽】T3 約束排列 解題報告
阿新 • • 發佈:2018-12-02
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; }