題目大意:
現有多個測例(測例以EOF結束),每個測例中第一行會給出要使用的小寫字母(不少於2個不超過20個不同的小寫字母,以空格隔開),第二行給出若干約束條件 ,約束條件不超過50個但至少有一條,約束形式如下"b a"表示b < a,即b必須排在a前面,對於每個測例都要求輸出所有滿足約束條件的序列,如果有多個序列滿足要求則按照字典序升序逐行打印出來,並且輸入保證一定有解(至少有1個解但不超過300個)。
註釋代碼:
/*
* Problem ID : POJ 1270 Following Orders
* Author : Lirx.t.Una
* Language : C++
* Run Time : 0 ms
* Run Memory : 124 KB
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <cstring>
#include <cstdio>
//最大字符數
#define MAXN 20
//臨時結束輸入的字符串(按行讀取)
#define FMTLEN 205
using namespace std;
char ch_set[MAXN + 1];//char_set,使用的字符集
char mp[MAXN];//將字符集按照從小到大排序後映射成數組下標(因爲要求按照字典序升序輸出解)
char deg[MAXN];//入度
bool g[MAXN][MAXN];//圖
char fmt[FMTLEN];
char path[MAXN + 1];//保存最後的結果
int n;//使用的字符的個數,即字符集的大小
int stp;//搜索的深度
void
dfs(void) {//按照字典序輸出必定使用深搜
int i, j;
if ( stp == n ) {
path[stp] = '\0';
puts(path);
return ;
}
for ( i = 0; i < n; i++ )//每一層都從小到大掃入度爲0的點
if ( !deg[i] ) {
path[stp++] = ch_set[i];
deg[i]--;
for ( j = 0; j < n; j++ )
if ( g[i][j] )
deg[j]--;
dfs();
for ( j = 0; j < n; j++ )//還原現場
if ( g[i][j] )
deg[j]++;
deg[i]++;
stp--;
}
}
int
main() {
int i, j;//計數變量
int u, v;//臨時點
int len;//臨時字符串的長度
while ( gets(fmt) ) {
memset(g, false, sizeof(g));
memset(deg, 0, sizeof(deg));
n = 0;
len = strlen(fmt);
for ( i = 0; i < len; i++ )//統計使用的字符個數放入ch_set中
if ( ' ' != fmt[i] )
ch_set[n++] = fmt[i];
sort(ch_set, ch_set + n);//排序
for ( i = 0; i < n; i++ ) mp[ ch_set[i] ] = i;//映射成數組下標
gets(fmt);
len = strlen(fmt);
for ( i = 0; i < len; i++ )
if ( fmt[i] != ' ' )
for ( j = i + 1; j < len; j++ )
if ( fmt[j] != ' ' ) {//兩個兩個篩出一組組關係
u = mp[ fmt[i] ];
v = mp[ fmt[j] ];
if ( g[u][v] ) {//由於輸入保證有解因此無需檢查環以及回邊
i = j;//跳到下一組
break;
}
//跟新邊以及入度
g[u][v] = true;
deg[v]++;
i = j;//同樣跳到下一組關係
break;
}
stp = 0;
dfs();
putchar('\n');
}
return 0;
}
無註釋代碼:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXN 20
#define FMTLEN 205
using namespace std;
char ch_set[MAXN + 1];
char mp[MAXN];
char deg[MAXN];
bool g[MAXN][MAXN];
char fmt[FMTLEN];
char path[MAXN + 1];
int n;
int stp;
void
dfs(void) {
int i, j;
if ( stp == n ) {
path[stp] = '\0';
puts(path);
return ;
}
for ( i = 0; i < n; i++ )
if ( !deg[i] ) {
path[stp++] = ch_set[i];
deg[i]--;
for ( j = 0; j < n; j++ )
if ( g[i][j] )
deg[j]--;
dfs();
for ( j = 0; j < n; j++ )
if ( g[i][j] )
deg[j]++;
deg[i]++;
stp--;
}
}
int
main() {
int i, j;
int u, v;
int len;
while ( gets(fmt) ) {
memset(g, false, sizeof(g));
memset(deg, 0, sizeof(deg));
n = 0;
len = strlen(fmt);
for ( i = 0; i < len; i++ )
if ( ' ' != fmt[i] )
ch_set[n++] = fmt[i];
sort(ch_set, ch_set + n);
for ( i = 0; i < n; i++ ) mp[ ch_set[i] ] = i;
gets(fmt);
len = strlen(fmt);
for ( i = 0; i < len; i++ )
if ( fmt[i] != ' ' )
for ( j = i + 1; j < len; j++ )
if ( fmt[j] != ' ' ) {
u = mp[ fmt[i] ];
v = mp[ fmt[j] ];
if ( g[u][v] ) {
i = j;
break;
}
g[u][v] = true;
deg[v]++;
i = j;
break;
}
stp = 0;
dfs();
putchar('\n');
}
return 0;
}