题目大意:
现有多个测例(测例以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;
}