user-0 提问: 蓝桥杯 算法提高 判断名次  求助~!

回复:
user: user-1
content: 引用 8 楼 china丶龙少 的回复:#include <iostream> #include <cstring> using namespace std;  int a[5], s1, s2, sum = 0;  bool judge(char *str) {     if(str[1] == '<' && str[2] >= '1' && str[2] <= '9')     {         if(a[str[0]-'A'] < str[2]-'0')             return 1;     }     if(str[1] == '<' && str[2] == '=')     {         if(a[str[0]-'A'] <= str[3]-'0')             return 1;     }     if(str[1] == '=')     {         if(a[str[0]-'A'] == str[2]-'0')             return 1;     }     if(str[1] == '>' && str[2] == '=')     {         if(a[str[0]-'A'] >= str[3]-'0')             return 1;     }     if(str[1] == '>' && str[2] >= '1' && str[2] <= '9')     {         if(a[str[0]-'A'] > str[2]-'0')             return 1;     }     if(str[1] == '!' &&str[2] == '=')     {         if(a[str[0]-'A'] != str[3]-'0')             return 1;     }     return 0; }  /* C<=3 A=1 B=1 E>=4 D!=2 */  int main() { 	char ans[20][10], saying[5][10];  	memset(ans, 0, sizeof(ans)); 	memset(saying, 0, sizeof(saying));  	for(int i = 0; i < 5; i++) 	{ 		cin >> saying[i]; 	}  	for(a[0] = 1; a[0] <= 5; a[0]++) 	{ 		for(a[1] = 1; a[1] <= 5; a[1]++) 		{ 			if(a[1] == a[0]) 				continue; 			for(a[2] = 1; a[2] <= 5; a[2]++) 			{ 				if(a[2] == a[0] || a[2] == a[1]) 					continue; 				for(a[3] = 1; a[3] <= 5; a[3]++) 				{ 					if(a[3] == a[0] || a[3] == a[1] || a[3] == a[2]) 						continue; 					for(a[4] = 1; a[4] <= 5; a[4]++) 					{ 						if(a[4] == a[0] || a[4] == a[1] || a[4] == a[2] || a[4] == a[3]) 							continue; 						//如果没有重复  						s1 = 0, s2 = 0;  						for(int i = 0; i < 5; i++) 						{ 							if(judge(saying[i])) 								s2++; 							else if(a[i] % 2) 								s1++; 						}  						if(s1 == 3 && s2 == 2) 						{ 							for(int i = 0; i < 5; i++) 								if(a[i] == 1) 									ans[sum++][0] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 2) 									ans[sum-1][1] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 3) 									ans[sum-1][2] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 4) 									ans[sum-1][3] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 5) 									ans[sum-1][4] = 'A' + i; 						} 					} 				} 			} 		} 	}  	char tmp[10]; 	for(int i = 0; i < sum - 1; i++)//字典序排列 		for(int j = 0; j < sum - 1 - i; j++) 		{ 			if(strcmp(ans[j], ans[j+1]) > 0) 			{ 				strcpy(tmp, ans[j]); 				strcpy(ans[j], ans[j+1]); 				strcpy(ans[j+1], tmp); 			} 		}  	for(int i = 0; i < sum; i++) 		cout << ans[i] << endl; 	cout << sum << endl;  	return 0; } 我改了以下，100分了

user: user-1
content: #include <iostream> #include <cstring> using namespace std;  int a[5], s1, s2, sum = 0;  bool judge(char *str) {     if(str[1] == '<' && str[2] >= '1' && str[2] <= '9')     {         if(a[str[0]-'A'] < str[2]-'0')             return 1;     }     if(str[1] == '<' && str[2] == '=')     {         if(a[str[0]-'A'] <= str[3]-'0')             return 1;     }     if(str[1] == '=')     {         if(a[str[0]-'A'] == str[2]-'0')             return 1;     }     if(str[1] == '>' && str[2] == '=')     {         if(a[str[0]-'A'] >= str[3]-'0')             return 1;     }     if(str[1] == '>' && str[2] >= '1' && str[2] <= '9')     {         if(a[str[0]-'A'] > str[2]-'0')             return 1;     }     if(str[1] == '!' &&str[2] == '=')     {         if(a[str[0]-'A'] != str[3]-'0')             return 1;     }     return 0; }  /* C<=3 A=1 B=1 E>=4 D!=2 */  int main() { 	char ans[20][10], saying[5][10];  	memset(ans, 0, sizeof(ans)); 	memset(saying, 0, sizeof(saying));  	for(int i = 0; i < 5; i++) 	{ 		cin >> saying[i]; 	}  	for(a[0] = 1; a[0] <= 5; a[0]++) 	{ 		for(a[1] = 1; a[1] <= 5; a[1]++) 		{ 			if(a[1] == a[0]) 				continue; 			for(a[2] = 1; a[2] <= 5; a[2]++) 			{ 				if(a[2] == a[0] || a[2] == a[1]) 					continue; 				for(a[3] = 1; a[3] <= 5; a[3]++) 				{ 					if(a[3] == a[0] || a[3] == a[1] || a[3] == a[2]) 						continue; 					for(a[4] = 1; a[4] <= 5; a[4]++) 					{ 						if(a[4] == a[0] || a[4] == a[1] || a[4] == a[2] || a[4] == a[3]) 							continue; 						//如果没有重复  						s1 = 0, s2 = 0;  						for(int i = 0; i < 5; i++) 						{ 							if(judge(saying[i])) 								s2++; 							else if(a[i] % 2) 								s1++; 						}  						if(s1 == 3 && s2 == 2) 						{ 							for(int i = 0; i < 5; i++) 								if(a[i] == 1) 									ans[sum++][0] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 2) 									ans[sum-1][1] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 3) 									ans[sum-1][2] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 4) 									ans[sum-1][3] = 'A' + i; 							for(int i = 0; i < 5; i++) 								if(a[i] == 5) 									ans[sum-1][4] = 'A' + i; 						} 					} 				} 			} 		} 	}  	char tmp[10]; 	for(int i = 0; i < sum - 1; i++)//字典序排列 		for(int j = 0; j < sum - 1 - i; j++) 		{ 			if(strcmp(ans[j], ans[j+1]) > 0) 			{ 				strcpy(tmp, ans[j]); 				strcpy(ans[j], ans[j+1]); 				strcpy(ans[j+1], tmp); 			} 		}  	for(int i = 0; i < sum; i++) 		cout << ans[i] << endl; 	cout << sum << endl;  	return 0; }

user: user-0
content: 谢谢各位!!

user: user-2
content: 直接全排列, 5!=120非常小,出来后还不需要排序, 大体框架如下,  void dfs(int d) {     if(d==5){         for(int i=0;i<5;i++){             int x =pos[i]&1,y=judge(i);//judge判断第i个人话为真或假, pos代表i的排名             if(x^y) return;         }         puts(a);         ++cnt;         return;     }     for(int i=0;i<5;i++) if(!vis[i]){         vis[i]=1;         a[d] =i+'A';         pos[i] =d;         dfs(d+1);         vis[i] =0;     } }

user: user-3
content: 引用 2 楼 lm_whales 的回复:假话则取 ，反说话内容 只要调换两个操作数次序即可哦这话说错了，请忽略 另一种方法是3人说谎，两人说实话 根据说话内容 判定名次，求出各种可能的组合。 然后排序输出 这种方法，判定复杂，但是待选情况较少，不需要遍历全排列

user: user-3
content: 穷举法具体做法： 对每个排列按照如下方法处理： 每个人说的话，可以看作表达式 做一个简单的表达式解析程序 ABCDE 作为变量名 12345 名次作为变量值 对A=2 这种关系表达式加以解析。 并根据说话人的身份(即名次，决定说的是真话还是假话)， 对表达式的值加以肯定（值不变）或否定（取反） 对每一个名次的可能组合（一个排列） 测试是否这五句话， 全符合说话人的身份（即上面计算结果是否全真）。  这样，再写一个枚举全排列的函数，即可实现穷举法。

user: user-4
content: 感觉就是个DFS枚举，5种状态枚举也枚举不了多久，而且还有那么多限制条件  根据题设条件直接先框定ABCDE的各自枚举范围 然后直接写递归就好了，最好不要像你这样子写代码，看着挺乱的

user: user-3
content: 假话则取 ，反说话内容 只要调换两个操作数次序即可

user: user-3
content: 最笨的方法穷举法： 枚举所有名次（全排列），假设没有并列名次，根据，说话内容和说话真假的组合，判断该排列是否是一个可能的名次。