POJ 1270 Following Orders

題目大意:

       現有多個測例(測例以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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章