9.14-回溯(//数字全排列//0-1背包//迷宫问题//八皇后问题//又一个迷宫//堡垒问题//三阶幻方//图的m着色问题//字母转换//输出命题公式的真值表)

1.数字全排列

           输出N个数字的所有排列组合情况

#include<iostream>

using namespace std;

void search(int m);
void output();

int n;
int arr[10];

int main(){
	cin >> n;
	for(int i = 0; i < n; i++){
	    arr[i] = i+1;
	}
	search(0); 
	return 0;
}

void search(int m){
	int tmp;
	if(m == n){
	    output();
	}
	else{
		//输出以第m个打头的所有组合
		for(int i = m; i < n; i++){
		    tmp = arr[i];   //交换arr[i]与arr[m]
			arr[i] = arr[m];
			arr[m] = tmp;
			search(m+1);
			tmp = arr[i];   //将arr[i]与arr[m]交换回来
			arr[i] = arr[m];
			arr[m] = tmp;
		}
	}
}

void output(){
	for(int i = 0; i < n; i++){
	    cout<<arr[i];
	}
	cout<<endl;
}

 

2.0-1背包

#include<iostream>

using namespace std;

int search(int m, int w);
void init();

int n, c;

struct bag{
    int weight, value;
}num[100];

int main(){
	init();
	cout << search(n, c) << endl; 
}

void init(){
    cin >> n >> c;
	for(int i = 0; i < n; i++){
	    cin >> num[i].weight;
	}
	for(int i = 0; i < n; i++){
	    cin >> num[i].value;
	}
}

int search(int m,int w){
	int i;
	if(m == 0 || w == 0){
	    return 0;
	}
	else{
		for(i = m-1; i >= 0; i--){
			if(num[i].weight > w){  //当前背包不能容纳,则不放入
				return search(m-1, w);
			}
		    else{
		        int tmp1 = search(m-1, w);  //不放入的价值
		        int tmp2 = num[i].value + search(m-1, w-num[i].weight);  //放入后的价值
				return(tmp1>tmp2 ? tmp1:tmp2);
		    }
		}
	}
}

智商不够,只能算出来最终结果,不能显示出最优解的具体情况。

 

3.迷宫问题

输入:先输入两个不超过20的正整数表示迷宫的行数m和列数n,再输入口和出口的坐标,最后分m行输入迷宫,其中1表示墙,0表示空格每个数字之间都有空格。

输出:只能向上、下、左、右四个方向走若能到达,则输出"Yes",否则输出"No",结果占一行。

输入样例:

3 3

0 0

2 2

0 0 0

1 1 0

0 1 0
输出样例:Yes

#include<iostream>
#include<queue>
using namespace std;

int m,n;
int gx, gy, tx, ty;
int arr[21][21];
int used[21][21];
int row[4] = {0, -1, 0, 1};
int col[4] = {1, 0, -1, 0};

struct{
	queue<int> q1;
	queue<int> q2;
}add;

int search(int x, int y);

int main(){
	cin >> m >> n;
	cin >> gx >> gy >> tx >> ty;
	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++){
			cin >> arr[i][j];
			if(arr[i][j] == 1){
				used[i][j] = 1;
			}
			else{
				used[i][j] = 0;
			}
		}
	}
	used[gx][gy] = 1;
	add.q1.push(gx);
	add.q2.push(gy);
	if(search(gx, gy)){
		cout << "Yes" <<endl;
	}
	else{
		cout << "No" << endl;
	}
}

int search(int x, int y){
	int e, f, nx, ny;
	while(1){
		if(add.q1.empty()){
			return 0;
		}
		else{
			e = add.q1.front();
	    	add.q1.pop();
		    f = add.q2.front();
	    	add.q2.pop();
		    for(int i = 0; i < 4; i++){
		    	nx = e + row[i];
			    ny = f + col[i];
			    if(nx == tx && ny == ty){
			     	return 1;
		    	}
			    if(nx < 0 || nx >= m || ny < 0 || ny >=n) continue;
			    if(!used[nx][ny]){
			    	used[nx][ny] = 1;
			    	add.q1.push(nx);
			    	add.q2.push(ny);
		    	}
	    	}
		}
	}
}

 

4.8皇后问题

描述:输出8皇后问题所有结果。

输入:没有输入。

输出:每个结果第一行是No n:的形式,n表示输出的是第几个结果;下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格。不同的结果中,先输出第一个皇后位置靠前的结果;第一个皇后位置相同,先输出第二个皇后位置靠前的结果;依次类推。

输出样例:输出的前几行:
No 1:
A.......
....A...
.......A
.....A..
..A.....
......A.
.A......
...A....
No 2:
A.......
.....A..
.......A
..A.....
......A.
...A....
.A......
....A...

提示:输出样例是正确输出结果的前几行。

#include<iostream>
#include<string.h>
using namespace std;

void search(int m);
void output();
int cando(int row, int col);

int map[8];
int cnt;

int main(){
	cnt = 1;
    search(0);
	return 0;
}

void search(int m){
	if(m == 8){
	    output();
	}
	else{
		for(int i = 0; i < 8; i++){
			if(cando(m, i)){
			    map[m] = i;
				search(m+1);
			}
		}
	}
}

int cando(int row, int col){
    int i;
	for(i = 0; i < row; i++){
		if(col == map[i] || (row-i == col-map[i]) || (row-i==map[i]-col)){
		    return 0;
		}
	}
	return 1;
}

void output(){
    int i, j;
	cout << "No " << cnt++ << ":" <<endl;
	for(i = 0; i < 8; i++){
		for(j = 0; j < 8; j++){
			if(map[i] == j){
			    cout << "A";
			}
			else{
			    cout << ".";
			}
		}
		cout << endl;
	}
}

 

5.又一个迷宫

描述:给一个20×20的迷宫、起点坐标和终点坐标,问从起点是否能到达终点。

输入:多个测例。输入的第一行是一个整数n,表示测例的个数。接下来是n个测例,每个测例占21行,第一行四个整数x1,y1,x2,y2是起止点的位置(坐标从零开始),(x1,y1)是起点,(x2,y2)是终点。下面20行每行20个字符,’.’表示空格;’X’表示墙。

输出:每个测例的输出占一行,输出Yes或No。

2
0 0 19 19
....................
XXXXXXXXXXXXXXXXXXXX
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
0 0 19 19
....................
XXXXXXXXXXXXXXXXXXX.
....................
.XXXXXXXXXXXXXXXXXXX
....................
XXXXXXXXXXXXXXXXXXX.
....................
.XXXXXXXXXXXXXXXXXXX
....................
XXXXXXXXXXXXXXXXXXX.
....................
.XXXXXXXXXXXXXXXXXXX
....................
XXXXXXXXXXXXXXXXXXX.
XXXXXXXXXXXXXXXXXXX.
XXXXXXXXXXXXXXXXXXX.
XXXXXXXXXXXXXXXXXXX.
....................
.XXXXXXXXXXXXXXXXXXX
....................

输出样例:

No
Yes

#include<iostream>
#include<queue>
using namespace std;
 
int n;
int gx, gy, tx, ty;
char arr[20][20];
int used[20][20];
int row[4] = {0, -1, 0, 1};
int col[4] = {1, 0, -1, 0};
 
struct{
	queue<int> q1;
	queue<int> q2;
}add;
 
int search(int x, int y);
 
int main(){
	cin >> n;
	while(n--){
	    cin >> gx >> gy >> tx >> ty;
	    for(int i = 0; i < 20; i++){
		    for(int j = 0; j < 20; j++){
			    cin >> arr[i][j];
			    if(arr[i][j] == 'X'){
				    used[i][j] = 1;
			    }
			    else{
				    used[i][j] = 0;
			    }
	    	}
	    }
	    used[gx][gy] = 1;
	    add.q1.push(gx);
	    add.q2.push(gy);
	    if(search(gx, gy)){
		    cout << "Yes" <<endl;
	    }
	    else{
		    cout << "No" << endl;
	    }
	}
}
 
int search(int x, int y){
	int e, f, nx, ny;
	while(1){
		if(add.q1.empty()){
			return 0;
		}
		else{
			e = add.q1.front();
	    	add.q1.pop();
		    f = add.q2.front();
	    	add.q2.pop();
		    for(int i = 0; i < 4; i++){
		    	nx = e + row[i];
			    ny = f + col[i];
			    if(nx == tx && ny == ty){
			     	return 1;
		    	}
			    if(nx < 0 || nx >= 20 || ny < 0 || ny >=20) continue;
			    if(!used[nx][ny]){
			    	used[nx][ny] = 1;
			    	add.q1.push(nx);
			    	add.q2.push(ny);
		    	}
	    	}
		}
	}
}

 

6.堡垒问题

描述:城堡是一个4×4的方格,为了保卫城堡,现需要在某些格子里修建一些堡垒。城堡中的某些格子是墙,其余格子都是空格,堡垒只能建在空格里,每个堡垒都可以向上下左右四个方向射击,如果两个堡垒在同一行或同一列,且中间没有墙相隔,则两个堡垒都会把对方打掉。问对于给定的一种状态,最多能够修建几个堡垒。

输入:每个测例以一个整数n(1<=n<=4)开始,表示城堡的大小。接下来是n行字符每行n个,‘X’表示该位置是墙,‘.’表示该位置是空格。n等于0标志输入结束。

输出:每个测例在单独的一行输出一个整数:最多修建堡垒的个数。

输入样例:

4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0

输出样例:

5
1
5
2
4

#include<iostream>
#include<string.h>
using namespace std;
 
void search(int m);
void output();
int cando(int t);
int min(int x, int y);
int max(int a, int b);

char tu[5][5];
int used[5][5];
int cnt;
int Max;
int n;
 
int main(){
	while(cin >> n && n){
		memset(tu, 0, sizeof(char));
		memset(used, 0, sizeof(used));
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
			    cin >> tu[i][j];
				if(tu[i][j] == 'X'){
				     used[i][j] = 2;
				}
			}
		}
	    cnt = 0;
		Max = 0;
        search(0);
		cout << Max << endl;
	}
}
 
void search(int m){
	if(m == n*n){
		if(Max < cnt){
		    Max = cnt;
		}
	}
	else{
		if(cando(m)){
			for(int i = 0; i < 2; i++){
				if(i == 0){
					cnt++;
			        used[m/n][m%n] = 1;
			        search(m+1);
			        used[m/n][m%n] = 0;
			        cnt--;
				}
				else{
					search(m+1);
				}
			} 	
		}
		search(m+1);
	}
	
}
 
int cando(int t){
    int i, j, row, col, flag;
	row = t/n;
	col = t%n;
	if(used[row][col] == 1 || used[row][col] == 2){
	    return 0;
	}
	else{
       /* flag = 1;
	    for(i = 0; i < n; i++){
		    if(used[row][i] == 1){
				for(j = min(col, i)+1; j < max(col, i); j++){
					if(used[row][j] == 2){
					     flag = 0;
                         break;
					}
				}
				if(flag){
				    return 0;
				}
				else{
				flag = 1;
				}
			}
			if(used[i][col] == 1){
				for(j = min(i, row)+1; j < max(i, row); j++){
					if(used[i][col] == 2){
					     flag = 0;
						 break;
					}
				}
                if(flag){
			        return 0;
			    }
				else{
				    flag = 1;
				}
			}
			
		}
		return (flag);*/
		if(row > 0){
			for(i = row-1; i >=0; i--){
			    if(used[i][col] == 1){
			        return 0;
			    }
			    else if(used[i][col] == 2){
			    	break;
		     	}
		    }
		}
		if(row < n-1){
			for(i = row+1; i < n; i++){
				if(used[i][col] == 1){
			        return 0;
			    }
			    else if(used[i][col] == 2){
			    	break;
		     	}
			}
		}
		if(col > 0){
			for(i = col-1; i >=0; i--){
				if(used[row][i] == 1){
					return 0;
				}
				else{
					break;
				}
			}
		}
		if(col < n-1){
			for(i = col+1; i < n; i++){
				if(used[row][i] == 1){
					return 0;
				}
				else{
					break;
				}
			}
		}
		return 1;
	}
}

int min(int x, int y){
    if(x < y){
    	return x;
    }
    else{
    	return y;
    }
}

int max(int a, int b){
    if(a > b){
    	return a;
    }
    else{
    	return b;
    }
}

 

7.三阶幻方

描述:三阶幻方是最简单的幻方,又叫九宫格,是由1,2,3,4,5,6,7,8,9九个数字组成的一个三行三列的矩阵,其对角线、横行、纵向的的和都为15。

输入:无

输出:按字典序输出所有的满足条件的幻方矩阵,每两个数字之间带一个空格,行尾无空格,每个幻方后带一个空行。

输入样例:无
输出样例:无

#include<iostream>
#include<string.h>
using namespace std;

void search(int m);
void output();
void judge();

int used[10];
int map[3][3];

int main(){
	 memset(map, 0, sizeof(map));
	 memset(used, 0, sizeof(used));
     search(0);
	 return 0;
}

void search(int m){
	if(m == 9){
	    judge();
	}
	else{
		for(int i = 1; i <=9; i++){
			if(used[i] == 0){
			    map[m/3][m%3] = i;
				used[i] = 1;
				search(m+1);
				used[i] = 0;
			}
		}
	}
}

void judge(){
    int i, j, flag = 1;
	for(i = 0; i < 3; i++){
		j = 0;
		if(map[i][j] + map[i][j+1] + map[i][j+2] != 15){
		    flag = 0;
		}
		else if(map[j][i] + map[j+1][i] + map[j+2][i] != 15){
		    flag = 0;
		}
	}
	if(map[0][0] + map[1][1] + map[2][2] != 15){
	    flag = 0;
	}
	if(map[0][2] + map[1][1] + map[2][0] != 15){
	    flag = 0;
	}
	if(flag){
	    output();
	}
}

void output(){
	int i, j;
	j = 0;
	for(i = 0; i < 3; i++){
	    cout <<map[i][j] <<" "<<map[i][j+1]<<" "<< map[i][j+2]<<endl;
	}
	cout <<endl;
}

 

8.图的m着色问题

描述:给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。

输入:第1行有3个正整数n,r 和m(n < 20,r < 200,m < 10),表示给定的图G有n个顶点和r条边,m种颜色。顶点编号为0,1,2,…,n-1。接下来的k行中,每行有2个正整数u,v,表示图G 的一条边(u,v)。

输出:输出不同的着色方案的总数。

输入样例:

3 2 2
0 1
1 2

输出样例:2

#include<iostream>
#include<string.h>
using namespace std;

void search(int t);

int n, r, m;
int map[21][21];
int color[11];
int ans;

int main(){
	int u, v;
	memset(map, 0, sizeof(map));
	memset(color, 0, sizeof(color));
	cin >> n >> r >> m;
	while(r--){
	    cin >> u >> v;
		map[u][v] = map[v][u] = 1;
	}
	ans = 0;
	search(0);
	cout << ans << endl;
    return 0;
}

void search(int t){
	if(t == n){
	    ans++;
	}
	else{
		for(int i = 0; i < m; i++){
			int flag = 1;
			for(int j = 0; j < t; j++){
				if(map[t][j] && color[j] == i){
				    flag = 0;
					break;
				}
			}
			if(flag){
			    color[t] = i;
				search(t+1);
			}
		}
	}
}

 

9.字母转换

描述:通过栈交换字母顺序。给定两个字符串,要求所有的进栈和出栈序列(i表示进栈,o表示出栈),使得字符串2在求得的进出栈序列的操作下,变成字符串1。输出结果需满足字典序。例如TROT 到 TORT:
[
i i i i o o o o
i o i i o o i o
]

输入:给定两个字符串,第一个字符串是源字符串,第二个字符是目标目标字符串。

输出:所有的进栈和出栈序列,输出结果需满足字典序

输入样例:

madam

adamm

bahama

bahama

long

short

eric

rice

输出样例:

[

i i i i o o o i o o

i i i i o o o o i o

i i o i o i o i o o

i i o i o i o o i o

]

[

i o i i i o o i i o o o

i o i i i o o o i o i o

i o i o i o i i i o o o

i o i o i o i o i o i o

]

[

]

[

i i o i o i o o

]

#include<iostream>
#include<stack>
using namespace std;

void dfs(int m);
void output();
bool judge();

stack <char> s;
char s1[1000];
char s2[1000];
char step[1000], ans[1000];
int len1, len2;
int cnt_in, cnt_out;

int main(){
	memset(s1, 0, sizeof(char));
	memset(s2, 0, sizeof(char));
	memset(step, 0 , sizeof(char));
	memset(ans, 0 ,sizeof(char));
	while(gets(s1) && s1!=NULL){
		gets(s2);
		cout << '[' << endl; 
		len1 = strlen(s1);
		len2 = strlen(s2);
		if(len1 == len2){
			cnt_in = 0;
			cnt_out = 0;
		    dfs(0);
		}
	    cout << ']' << endl;
	    memset(s1, 0, sizeof(char));
	    memset(s2, 0, sizeof(char));
		memset(step, 0 ,sizeof(char));
		memset(ans, 0, sizeof(char));
	}
}

void dfs(int m){
	if(m == len1*2 && judge()){
	    output();
	}
	else{
		if(cnt_in < len1){
            cnt_in++;
			step[m] = 'i';
			dfs(m+1);
			cnt_in--;
		}
		if(cnt_out < cnt_in){
		    cnt_out++;
			step[m] = 'o';
			dfs(m+1);
			cnt_out--;
		}
	}
}

bool judge(){
    int i, j, k;
	j = 0; k = 0;
	for(i = 0; i < len1*2; i++){
		if(step[i] == 'i'){
		    s.push(s1[j++]);
		}
		else{
		    ans[k++] = s.top();
			s.pop();
		}
	}
	for(i = 0; i < len1; i++){
		if(ans[i] != s2[i]){
		    return false;
		}
	}
	return true;
}

void output(){
    int i;
	for(i = 0; i < len1*2-1; i++){
	    cout << step[i] << " ";
	}
	cout << step[i];
	cout << endl;
}

 

10.输出命题公式的真值表

描述:先输入一个正整数n(n小于等于10),表示共有n个命题变元,再输入一个类似于逆波兰表达式的字符串表示一个命题公式,约定在该字符串中用一位的十进制数表示一个命题变元,用a、o、n、i、e分别表示且、或、非、蕴含、等值,用类似于逆波兰表达式形式的字符串表示的命题公式的真值表波兰表达式(即二元运算,两个操作数在前,运算符在后;一元运算,一个操作数在前,运算符在后)。

输入:先输入一个小于等于10的正整数n,再输入一个字符串。

输出:输出该字符串表示的命题公式的真值表。
提示:如果用P、Q、R分别表示这三个命题变元的话,
输入数据01a2i表示的命题公式是:((P∧Q)→R)
输入数据012ia表示的命题公式是:(P∧(Q→R))
输入数据0n表示的命题公式是:┐P

输入样例

3
01a2i

输出样例

0 0 0 1
0 0 1 1
0 1 0 1
0 1 1 1
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 1

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

int arr[10];
char a[10];
int n;

void search(int m);
void init();
void output();

int main(){
	init();
	search(0);
}

void init(){
	char tmp[20];
	int s, cnt = 0;
    cin >> n;
    scanf("%s", &tmp);
	for(int i = 0; i < strlen(tmp); i++){
		s = tmp[i] - '0';
		if(s>=0 && s<=9){
			continue;
		}
		else{
			a[cnt] = tmp[i];
			cnt++;
		}
	}
}

void search(int m){
	if(m == n){
	    output();
	}
	else{
		for(int i = 0; i < 2; i++){
		    arr[m] = i;
			search(m+1);
		}
	}
}

void output(){
	int tmp = arr[0], i;
	for(i = 0; i < n; i++){
	    cout << arr[i] << " ";
	}
	for(i = 0; i < n-1; i++){
		if(a[i] == 'a'){
		    tmp = tmp&arr[i+1];
		}
		else if(a[i] == 'o'){
		    tmp = tmp|arr[i+1];
		}
		else if(a[i] == 'n'){
		    tmp = ~tmp;
		}
		else if(a[i] == 'i'){
			if(tmp == 1 && arr[i+1] == 0){
			    tmp = 0;
			}
			else{
			    tmp = 1;
			}
		}
		else if(a[i] == 'e'){
			if(tmp == arr[i+1]){
				tmp = 1;
			}
			else{
				tmp = 0;
			}
		}
	}
	cout << tmp << endl;
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值