POJ1270 Following Orders——拓扑排序(DFS回溯+字典序)

点这里


题意: 多组输入,每组输入的第一行列出受约束的字符。第二行每对字符a、b表示a必须排在b的前面。要求输出所有可行的情况,按字典序排序。结尾用空行分开。
题解: 不同以往的数字,这次受约束的是小写字母,可以在排序之后将字母转换成数字,也可以利用map来解决。因为要输出所有可行的情况,所以需要用DFS,并且还得回溯。


过程中犯的错:

  • 字典序。 又是偷懒读题,因为题面是英文的,缺乏耐心,以为自己读懂题就不继续往下读了,然后就漏了这么一个大条件。
  • 第二行约束条件的获取。 读完题目自然知道清楚每两个字符构成一对。然后每个字母之间都用空格隔开,那么自然就能推到出每个字母的下标,所以我写出了下面这个程序。应该说有点想当然了,后来这里改了就能通过。
for(int i = 2; line[i]; i += 4){
	char a = line[i - 2], b = line[i];
	v[a - 'a'].push_back(b);
	deg[b]++;
}

直接处理字符,DFS中传字符串

#include
#include
#include
#include
#include
using namespace std;
const int N = 1000;

char line[N], s[N];
string str;
vector<char> v[N];
map<char, int> deg;
void DFS(string ans){
	if(ans.length() == str.length()){
		cout << ans << endl;	return;}	
	for(int i = 0; str[i]; i++){
		string tem = ans;
		if(deg[str[i]] == 0){
			deg[str[i]]--;
			for(int j = 0; j < v[str[i] - 'a'].size(); j++)	deg[v[str[i] - 'a'][j]]--;
			tem += str[i]; DFS(tem);
			deg[str[i]]++;
			for(int j = 0; j < v[str[i] - 'a'].size(); j++)	deg[v[str[i] - 'a'][j]]++;
		}
	}
}
int main(){
	while(gets(line) != NULL){
		int cnt = 0; deg.clear();	str = "";
		for(int i = 0; i < 30; i++)	 v[i].clear();
		for(int i = 0; line[i]; i++)
			if(line[i] >= 'a' && line[i] <= 'z')	str += line[i];
		sort(str.begin(), str.end());
		gets(line);
		int flag = 1;char u, t;
		for(int i = 0; line[i]; i++){
			if(line[i] >= 'a' && line[i] <= 'z'){
				if(flag)	u = line[i], flag = 0;
				else{
					t = line[i], flag = 1;
					v[u - 'a'].push_back(t);
					deg[t]++;
				}
			}
		}
		string ans = "";
		DFS(ans); puts("");
	}
	return 0;
}

字符转成数字,DFS中传字符长度

#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 1e3 + 10;

int G[N][N], deg[N], cnt;
char line[N], str[N], ans[N];
map<char, int> mp;
void DFS(int len){
	if(len == cnt){	printf("%s\n", ans); return ;}
	for(int i = 0; i < cnt; i++){
		if(deg[i] == 0){
			deg[i]--;
			ans[len] = str[i];
			for(int j = 0; j < cnt; j++)	if(G[i][j])	deg[j]--;
			DFS(len + 1);
			deg[i]++;
			for(int j = 0; j < cnt; j++)	if(G[i][j])	deg[j]++;
		}
	}
}
void init(){
	cnt = 0;
	memset(G, 0, sizeof G);
	memset(ans, 0, sizeof ans);
	memset(deg, 0, sizeof deg);
	mp.clear();
}
int main(){
	while(gets(line) != NULL){
		init();
		for(int i = 0; line[i]; i++) if(line[i] >= 'a' && line[i] <= 'z') str[cnt++] = line[i];
		sort(str, str + cnt);
		for(int i = 0; i < cnt; i++)	mp[str[i]] = i;
		gets(line);
		int flag = 1, tem1, tem2;
		for(int i = 0; line[i]; i++)
			if(line[i] >= 'a' && line[i] <= 'z')
				if(flag)	tem1 = mp[line[i]], flag = 0;
				else{
					tem2 = mp[line[i]], flag = 1;
					deg[tem2]++;
					G[tem1][tem2] = 1;
				}
		DFS(0); puts("");
	}
	return 0;
}

你可能感兴趣的:(刷题,搜索技术,#,拓扑排序)