【训练题:回溯2】

Q1:没什么好说的,前后双指针,加一减一。

vector<string> input(20,"");
vector<string> output(20,"");
void solve(vector<string>& input,vector<string>& output,int n){
	int front=0,back=n-1;
	for(int i=0;i<n;i+=2){
		output[back--] = input[i+1];
		output[front++] = input[i];
	}
}
int main()
{  
   int n;
   int cnt=1;
   while(cin>>n&&n){
       for(int i=0;i<n;i++){
       		  cin>>input[i];
	   } 
	   solve(input,output,n);
	   cout<<"SET "<<cnt++<<endl;
	   for(int i=0;i<n;i++){
	   	cout<<output[i]<<endl;
	   }
   } 
   return 0;	
}

Q2:剪支 大剪支 大大剪支:

int n,maxLen,sum,num;
int used[110];
int part[110];
bool cmp(const int& a,const int& b){
	return a>b;
}
void init(){
	maxLen=0;
	sum=0;
	memset(used,0,sizeof(used));
	for(int i=0;i<n;i++){
		scanf("%d",&part[i]);
		maxLen = max(maxLen,part[i]);
		sum+=part[i];
	}
}
//深搜 
//怎么剪支呢??? 
bool dfs(int cur,int tar,int cnt,int start){//cur 当前长度 tar 目标长度 cnt 组成木棍数目 
	if(cnt==n)	return true;
	int pre=-1;
	for(int i=start;i<n;i++){
		if(used[i]||part[i]==pre)	continue;
		used[i] = 1;
		if(cur+part[i]<tar){
			if(dfs(cur+part[i],tar,cnt+1,i))
			    return true;
            else
                pre = part[i];
		}else if(cur+part[i]==tar){
			if(dfs(0,tar,cnt+1,0))
			    return true;
            else
                pre = part[i];
		}
		used[i] = 0;
		if(cur==0)//这个意思是 构建新棒时,对于新棒的第一根棒子,在搜索完所有棒子后都无法组合
                  //则说明该棒子无法在当前组合方式下组合,不用往下搜索(往下搜索会令该棒子被舍弃),直接返回上一层
		    break;
	}
	return false;
} 
int main()
{  
    while(cin>>n&&n){
    	init();
    	int f=0;
    	sort(part,part+n,cmp);
    	for(int i=maxLen;i<=sum-maxLen;i++){
    		if(sum%i==0){
    			if(dfs(0,i,0,0)){
    				printf("%d\n",i);
    				f=1;
    				break; 
				}
			} 
		}
		if(!f){
			printf("%d\n",sum);
		 } 
	}
   return 0;	
}

Q3:经典的八皇后问题:

int ans;
void solve(int r,int n,vector<int>& flag_col,vector<int>& flag_45,vector<int>& flag_135,int sum){
    if(r==n){
        ans = max(ans,sum);
        return ;
    }                   
    for(int j=0;j<n;j++){
        if(flag_col[j]&&flag_45[r+j]&&flag_135[n-1+j-r]){
            flag_col[j]=flag_45[r+j]=flag_135[n-1+j-r]=0;  
            sum+=board[r][j];
            solve(r+1,n,flag_col,flag_45,flag_135,sum);                
            flag_col[j]=flag_45[r+j]=flag_135[n-1+j-r]=1;
            sum-=board[r][j];
        }
    }      
}
void print(){
	ans=0;
	vector<int> flag_col(8,1),flag_45(2*8-1,1),flag_135(2*8-1,1);  
	for(int i=0;i<8;i++){
		for(int j=0;j<8;j++){
			cin>>board[i][j];
		}
	}
	solve(0,8,flag_col,flag_45,flag_135,0);
	printf("%5d\n",ans);
}
int main()
{  
   int k;cin>>k;
   while(k--){
   print();
   }
   return 0;	
}

Q4:简单回溯,数据量很小,直接暴力搜索:

int n,m,ans;
int mat[30][30];
int vis[30][30];
void solve(int u,int p){
	ans = max(ans,p);
	for(int i=0;i<n;i++){
		if(mat[u][i]&&!vis[u][i]){//u~i 可达且未访问过 
            vis[u][i]=1;
            vis[i][u]=1;
			solve(i,p+1);
			vis[u][i]=0;//回溯
			vis[i][u]=0; 
		}
	}
}
int main()
{  
    while(cin>>n>>m&&(n||m)){
    	ans=0;
    	memset(mat,0,sizeof(mat));
    	for(int i=0;i<m;i++){
            int x,y;
			cin>>x>>y;
			mat[x][y]=1;
			mat[y][x]=1;
	    }
    	for(int i=0;i<n;i++){//起点 
    		memset(vis,0,sizeof(vis));	
    		solve(i,0);
		}
    	cout<<ans<<endl;
	}
   return 0;	
}

Q5:不要把问题想得复杂了,简单的DFS就好:

int w,h,r,c,ans;
char mat[30][30];
int dir[4][2] = {{-1,0},{0,-1},{0,1},{1,0}};
void init(){
	ans=0;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			cin>>mat[i][j];
			if(mat[i][j]=='@'){
				r = i;
				c = j;
				mat[i][j] = '.';
			}
		}
	}
}
void solve(int row,int col){
	if(row<0||row>=h||col<0||col>=w||mat[row][col]=='#')
	return ;
	mat[row][col] = '#';
	ans++;
	for(int i=0;i<4;i++){
		solve(row+dir[i][0],col+dir[i][1]);
	}
}
int main()
{  
    while(cin>>w>>h&&(w||h)){
    	init();
    	solve(r,c);
    	printf("%d\n",ans);
	}
   return 0;	
}

猜你喜欢

转载自blog.csdn.net/Csdn_jey/article/details/90646683