实验二

本文深入探讨了八皇后问题、素数环问题、图的m着色问题等经典回溯算法案例,通过详细的代码实现,解析了算法的设计思路与运行过程,为读者提供了一个全面理解回溯算法的视角。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

八皇后问题

#include<iostream>
using namespace std;
int a[10][10],Count=0; 
void make(int m);
int main(){
	make(0);
	return 0;
} 
void make(int m){//已经填了几行 
	//cout<<m<<endl; 
	if(m==8){
		Count++;
		cout<<"No "<<Count<<":"<<endl;
		for(int i=0;i<8;i++){
			for(int j=0;j<8;j++){
				if(a[i][j]==1){
					cout<<"A";
				}
				else if(a[i][j]==0){
					cout<<".";
				}
			}
			cout<<endl;
		}
	}
	else{
		for(int i=0;i<8;i++){//判断8个位置是否可以放下,若能则m+1;都不能则return
			int flag=1; 
			for(int j=0;j<m;j++){//不能则设置flag为0 
				if(a[j][i]==1||
				(i-(m-j)>=0&&a[j][i-(m-j)]==1)||
				(i+(m-j)<8&&a[j][i+(m-j)]==1)){
					flag=0;
				}
			}
			if(flag==1){
				a[m][i]=1;
				make(m+1);
				a[m][i]=0;
			} 
		}
	}
}

素数环问题

#include<iostream>
using namespace std;
int p[50],a[25],flag=0;
void dfs(int n);
int main(){
	p[2]=p[3]=p[5]=p[7]=p[11]=p[13]=p[17]=p[19]=p[23]=p[29]=p[31]=p[37]=1;
	dfs(0);
	return 0;
}
void dfs(int n){
	if(flag==1)return;
	else if(n==20&&p[a[19]+a[0]]==1){
		flag=1;
		for(int i=0;i<19;i++){
			cout<<a[i]<<' ';
		}
		cout<<a[19]<<endl;
	}
	else if(n==0){
		for(int i=1;i<=20;i++){
			a[0]=i;
			dfs(1);
		}
	}
	else{
		for(int i=1;i<=20;i++){
			int is_used=0;
			for(int j=0;j<n;j++){
				if(a[j]==i){
					is_used=1;
					break;
				}
			}
			if(is_used==0&&p[a[n-1]+i]==1){
				a[n]=i;
				dfs(n+1);
			}
		}
	}
}

图的m着色问题

#include<iostream>
using namespace std;
int G[25][25];//0,1表示是否有边 
int a[25];//0表示还没有涂色 
int n,r,m,x,y,num=0; 
void dfs(int k);
int main(){
	cin>>n>>r>>m;
	for(int i=0;i<r;i++){
		cin>>x>>y;
		G[x][y]=G[y][x]=1;
	}
	dfs(0);
	cout<<num<<endl;
	return 0;
}
void dfs(int k){
	if(k==n)num++;
	else{
		for(int i=1;i<=m;i++){//尝试对第k个涂i色 
			int flag=1;
			for(int j=0;j<k;j++){
				if(j!=k&&G[k][j]==1&&a[j]==i){
					flag=0;
					break;
				}
			}
			if(flag==1){
				a[k]=i;
				dfs(k+1);
				a[k]=0;
			} 
		}
	}
}

0-1背包问题

#include<iostream>
using namespace std;
int n,c;
int cmax,tw,tp;
int w[15],p[15];
int a[15];
void dfs(int k);
int main(){
	cin>>n>>c;
	while(n!=0||c!=0){
		cmax=0;tw=tp=0;
		for(int i=0;i<n;i++){
			cin>>w[i];
		}
		for(int i=0;i<n;i++){
			cin>>p[i];
		}
		dfs(0);
		cout<<cmax<<endl;
		cin>>n>>c;
	}
}
void dfs(int k){
	if(k==n){
		if(tp>cmax)cmax=tp;
	}
	else{
		//剪枝,后面全选都不会更好 
		int sump=0;
		for(int i=k;i<n;i++){
			sump+=p[i];
		}
		if(sump+tp<=cmax)return;
		//尝试选k
		if(tw+w[k]<=c){
			a[k]=1;
			tp+=p[k];
			tw+=w[k]; 
			dfs(k+1);
			tp-=p[k];
			tw-=w[k];
		}
		//尝试不选k 
		a[k]=0;
		dfs(k+1); 
	}
}

踩气球

#include<iostream>
#include<cstring>
using namespace std;
int x,y;
int n1,n2;
void dfs(int k);
int mark[4];
int main(){
	cin>>x>>y;
	while(x!=0&&y!=0){
		memset(mark,0,sizeof(0));
		if(x>y){
			int t=x;x=y;y=t;
		}
		n1=n2=1;
		dfs(2);
		//cout<<"m0:"<<mark[0]<<endl;
		if(mark[0]){
			cout<<y<<endl;
		}
		else if(mark[1])cout<<x<<endl;
		else{
			cout<<y<<endl;
		}
		cin>>x>>y;
	}
	return 0;
}
void dfs(int k){
	//cout<<k<<endl;
	if(k<=100&&(n1*k<=x||n2*k<=y)&&(x/n1*n1==x)&&(y/n2*n2==y)){
		//第一个人踩气球 
		n1*=k;
		//cout<<n1<<endl;
		if(n1==x&&n2==y){
			mark[0]=1;
			//cout<<n1<<' '<<n2<<endl;
		}
		else if(n1==x){
			mark[1]=1;
			//cout<<n1<<' '<<n2<<endl;
		}

		dfs(k+1);
		n1/=k;
		//第二个人踩气球
		n2*=k;
		
		if(n1==x&&n2==y)mark[0]=1;
		else if(n1==x)mark[1]=1;
		
		dfs(k+1);
		n2/=k;
		//都不踩气球 
		dfs(k+1);
	}
} 

装载问题

#include<iostream>
using namespace std;
int x,y,n,flag;
int w[15];
int w1,w2;
void dfs(int k);
int main(){
	cin>>x>>y>>n;
	while(n!=0){
		flag=0;
		w1=w2=0;
		for(int i=0;i<n;i++){
			cin>>w[i];
		}
		dfs(0);
		if(flag)cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
		cin>>x>>y>>n;
	}
	return 0;
}
void dfs(int k){
	if(flag==1)return;
	else if(k==n){
		flag=1;
		return;
	}
	else{
		if(w1+w[k]<=x){
			w1+=w[k];
			dfs(k+1);
			w1-=w[k];
		}
		if(w2+w[k]<=y){
			w2+=w[k];
			dfs(k+1);
			w2-=w[k];
		}
	}
}

求图像的周长

#include<iostream>
#include<cstring>
using namespace std;
int m,n,x,y,sum=0;
char map[110][110];
int a[110][110];//存储这个格子可以扩展的方向数i,则边数为4-i 
int dx[8]={0,1,1,1,0,-1,-1,-1}; 
int dy[8]={-1,-1,0,1,1,1,0,-1};
bool used[110][110];
void dfs(int x,int y);
int main(){
	cin>>m>>n>>x>>y;
	while(m!=0){
		memset(a,0,sizeof(a));
		memset(map,0,sizeof(map));
		memset(used,0,sizeof(used));
		sum=0;
		for(int i=1;i<=m;i++){
			for(int j=1;j<=n;j++){
				cin>>map[i][j];
			}
		}
		dfs(x,y);
		cout<<sum<<endl;
		cin>>m>>n>>x>>y;
	}
	return 0;
}
void dfs(int x,int y){
	used[x][y]=1;
	for(int i=0;i<8;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(tx<=m&&tx>0
		&&ty<=n&&ty>0
		&&map[tx][ty]=='X'){
			if(i%2==0)a[x][y]++;
			if(used[tx][ty]==0)dfs(tx,ty);
		}
	}
	sum+=(4-a[x][y]);
} 

农场灌溉问题

#include<iostream>
#include<cstring>
using namespace std;
int m,n,sum=0;
char ch;
int a[15]={9,3,12,6,5,10,11,13,14,7,15};
int map[55][55];
int used[55][55];
void dfs(int x,int y);
int main(){
	cin>>m>>n;
	while(m!=-1&&n!=-1){
		sum=0;
		memset(used,0,sizeof(used));
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				cin>>ch;
				map[i][j]=a[ch-'A'];
			}
		}
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				if(used[i][j]==0){
					sum++;
					dfs(i,j);
				}
			}
		}
		cout<<sum<<endl;
		cin>>m>>n;
	}
	return 0;
}
void dfs(int x,int y){
	used[x][y]=1;
	int num=map[x][y];
	if(num&1&&x-1>=0){
		if(used[x-1][y]==0&&(map[x-1][y]>>2)&1)dfs(x-1,y);
	}
	if((num>>1)&1&&y+1<n){
		if(used[x][y+1]==0&&(map[x][y+1]>>3)&1)dfs(x,y+1);
	}
	if((num>>2)&1&&x+1<m){
		if(used[x+1][y]==0&&(map[x+1][y])&1)dfs(x+1,y);
	}
	if((num>>3)&1&&y-1>=0){
		if(used[x][y-1]==0&&(map[x][y-1]>>1)&1)dfs(x,y-1);
	}
}

字母转换

#include<iostream>
#include<string>
#include<queue>
#include<stack>
using namespace std;
string a,b,t;
int ar[110];
char ch;
queue<char> q;
stack<char> s;

void dfs(int k);
int main(){
	while(cin>>a>>b){
		cout<<"["<<endl;
		dfs(0);
		cout<<"]"<<endl;
	}
	return 0;
}
void dfs(int k){
	if(k==a.size()*2){
		while(!q.empty()){
			q.pop();
		}
		while(!s.empty()){
			s.pop();
		}
		t.erase(0);
		for(int i=0;i<a.size();i++){
			q.push(a[i]);
		}
		for(int i=0;i<k;i++){
			if(ar[i]==1){
			ch=q.front();
			q.pop();
			s.push(ch);	
			}
			else{
				ch=s.top();
				s.pop();
				t+=ch;
			}
		}
		if(b==t){
			for(int i=0;i<k-1;i++){
				if(ar[i])cout<<'i'<<' ';
				else cout<<'o'<<' ';
			}
			if(ar[k-1])cout<<'i';
			else cout<<'o';
			cout<<endl;
		}
	}
	else{
		//尝试填1(对应入栈) 
		int num=0;
		for(int i=0;i<k;i++){
			if(ar[i]==1)num++;
		}
		if(num<a.size()){
			ar[k]=1;
			dfs(k+1); 
		}
		//尝试填0(对应出栈) 
		int flag=1,na=0,nb=0;
		for(int i=0;i<k;i++){
			if(ar[i]==1)na++;
			if(ar[i]==0)nb++;
		}
		if(na>nb){
			ar[k]=0;
			dfs(k+1);
		}
	}
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值