第三章 习题(三)

5-12 罗密欧与朱丽叶的迷宫问题

注意:还可加入无解时的剪枝判断

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. using namespace std;  
  5.   
  6. const int NM=25;  
  7. int d[8][2]={-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};  
  8. int vis[NM][NM],path[NM][NM],x[NM*NM],y[NM*NM],cc,gx,gy,n,m,ans,WAN;  
  9. bool flag;  
  10. struct Node{  
  11.     int x,y,dir,wan;  
  12. };  
  13.   
  14. void Backtrack(Node t,int kk)  
  15. {  
  16.     int i;  
  17.     Node pt;  
  18.       
  19.     if(t.x==gx && t.y==gy){  
  20.         if(kk<cc) return;  //  
  21.         flag=1;  
  22.         if(t.wan<=WAN) {  
  23.             if(t.wan<WAN) {  
  24.                 WAN=t.wan;ans=1;  
  25.                 for(i=0;i<=cc;i++)  
  26.                     path[x[i]][y[i]]=i+2;  
  27.             }  
  28.             else if(t.wan==WAN) ans++;  
  29.         }  
  30.         return;  
  31.     }  
  32.       
  33.     if(t.wan>WAN || kk==cc) return;  
  34.     for(i=0;i<8;i++){  
  35.         pt.x=t.x+d[i][0];pt.y=t.y+d[i][1];  
  36.         if(pt.x>0 &&pt.x<=n &&pt.y>0 && pt.y<=m && vis[pt.x][pt.y]!=-1){  
  37.             if(t.dir!=i) t.wan++;  
  38.             pt.dir=i;pt.wan=t.wan;  
  39.             vis[pt.x][pt.y]=-1;  
  40.             x[kk]=pt.x;y[kk]=pt.y;  
  41.   
  42.             Backtrack(pt,kk+1);  
  43.             vis[pt.x][pt.y]=0;  
  44.             if(t.dir!=i) t.wan--;  
  45.             x[kk]=y[kk]=0;  
  46.         }  
  47.     }  
  48. }  
  49.   
  50. int main()  
  51. {  
  52.     int i,j,k,x,y,bx,by;  
  53.     Node pt;  
  54.     while(~scanf("%d%d%d",&n,&m,&k))  
  55.     {  
  56.         for(i=0;i<k;i++){  
  57.             scanf("%d%d",&x,&y);  
  58.             path[x][y]=vis[x][y]=-1;  
  59.         }  
  60.         scanf("%d%d",&bx,&by);  
  61.         scanf("%d%d",&gx,&gy);  
  62.           
  63.         vis[bx][by]=-1;//vis[gx][gy]=2;  
  64.         path[bx][by]=1;path[gx][gy]=10;  
  65.         cc=n*m-1-k;  
  66.         WAN=0xfffffff;  
  67.         ans=0;  
  68.         pt.x=bx;pt.y=by;pt.wan=-1;pt.dir=0;  
  69.         flag=false;  
  70.         Backtrack(pt,0);  
  71.           
  72.         if(!flag) {  
  73.             printf("No solution!\n");continue;  
  74.         }  
  75.         printf("%d\n%d\n",WAN,ans);  
  76.         for(i=1;i<=n;i++){  
  77.             for(j=1;j<=m;j++){  
  78.                 printf("%d ",path[i][j]);  
  79.             }  
  80.             printf("\n");  
  81.         }  
  82.     }  
  83.     return 0;  
  84. }  
  85. /* 
  86. 2 2 1 
  87. 1 2 
  88. 1 1 
  89. 2 2 
  90. 4 5 2 
  91. 1 5 
  92. 3 3 
  93. 1 1 
  94. 4 4 
  95. */  


5-16 无优先级运算问题

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

const int NM=25;
int a[NM],vis[NM],save[NM],f[NM],k,n,m;
char sf[4]={'+','-','*','/'};
bool flag;

bool Backtrack(int t,int res)
{
	int i,j;
	if(res==m) {
			flag=true;
			for(i=1;i<t;i++) {
				cout<<save[i];
				if(i<t-1) cout<<sf[f[i]];
			}
			cout<<endl;
			return true;
	}
	if(t>k)	{
		return false;
	}
	
	for(j=0;j<n;j++)
	{
		if(t==1) {
			vis[j]=1;save[t]=a[j];
			Backtrack(t+1,a[j]);
			if(flag) return true;
			vis[j]=0;save[t]=0;
		}
		else  //
		if(!vis[j]){
			vis[j]=1;save[t]=a[j];
			for(i=0;i<4;i++){
				f[t-1]=i;
				if(i==0) Backtrack(t+1,res+a[j]);
				else if(i==1) Backtrack(t+1,res-a[j]);
				else if(i==2) Backtrack(t+1,res*a[j]);
				else {
					if(res%a[j]==0) Backtrack(t+1,res/a[j]);
				}
				if(flag) return true;
			}
			vis[j]=0;save[t]=0;
		}
	}
	return false;
}

void compute()
{
	int mmaxk=25;
	memset(vis,0,sizeof(vis));
	k=2;
	while(!Backtrack(1,0)){
		memset(vis,0,sizeof(vis));
		if(k>mmaxk) break;
		k++;
	}
}

int main()
{
	int i;
	while(cin>>n)
	{
		for(i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		cin>>m;
		flag=false;
		compute();
		if(!flag) cout<<"No solution!"<<endl;
	}
	return 0;
}
/*
10 111
1 6 7 7 8 9 44 33 55 66

4 5
1 3 1 2 

2 5
1 6

*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值