本文主要是介绍递归【1】(全排列andN皇后)(排列型回溯),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
全排列
分治与递归
递归是实现分治的一种方法
思想思路
题目:
全排列i
我这样直接输出会多输出一个空行(最后一个\n)
#include<stdio.h>using namespace std;
const int maxn=10;
int an[maxn];
int n;
bool hash[maxn]={0};
int c=0;
void pl(int index)
{if (index>n-1)
{for (int i=0;i<n-1;i++)printf("%d ",an[i]);printf("%d",an[n-1]);printf("\n");return;} for(int i=1;i<=n;i++){if (!hash[i]){an[index]=i;hash[i]=1;pl(index+1);c++;hash[i]=0;}}} int main(){scanf("%d",&n);pl(0);}
使用vector存储,在最后一格时不输出
参考解答
#include <cstdio>
#include <vector>
using namespace std;const int MAXN = 8 + 1;
vector<vector<int> > result;
vector<int> temp;
int n;
bool used[MAXN] = {false};void DFS(int idx) {if (idx == n + 1) {result.push_back(temp);return;}for (int i = 1; i <= n; i++) {if (!used[i]) {temp.push_back(i);used[i] = true;DFS(idx + 1);used[i] = false;temp.pop_back();}}
}int main() {scanf("%d", &n);DFS(1);for (int i = 0; i < result.size(); i++) {for (int j = 0; j < result[i].size(); j++) {printf("%d", result[i][j]);printf(j + 1 < result[i].size() ? " " : "\n");}}return 0;
}
我也改好了
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=10;
//int an[maxn];
vector<vector<int> > ans;
vector<int> temp;
int n;
bool hasha[maxn]={0};
int c=0;
void pl(int index)
{if (index>n-1)
{
//for(int j=0;j<temp.size();j++)printf("%d ",temp[j]);ans.push_back(temp);
// for (int i=0;i<n-1;i++)
// printf("%d ",an[i]);
// printf("%d",an[n-1]);
// printf("\n");
// return;} for(int i=1;i<=n;i++){if (!hasha[i]){temp.push_back(i);hasha[i]=1;pl(index+1);hasha[i]=0;temp.pop_back();
// an[index]=i;
// hash[i]=1;
// pl(index+1);
// c++;
// hash[i]=0;}}} int main(){scanf("%d",&n);pl(0);for(int i=0;i<ans.size();i++){for(int j=0;j<n;j++){printf("%d",ans[i][j]);if (j<n-1)printf(" ");}if(i<ans.size()-1)printf("\n");}}
N皇后
判断8皇后
弃用数组,研究vector的用法搞了半天关于vector的一些菜鸟吐槽-CSDN博客
首先弄明白bool
true是1,false是0
用了二维vector,加上各种边界条件总算搞出来了
可是时间复杂度on3
#include<stdio.h>
#include<vector>
#include<iostream>
using namespace std;
int n=8;
vector<vector<int> > a=vector<vector<int> >(8, vector<int>(8, 0));;
// vector<vector<int> > board = vector<vector<int> >(8, vector<int>(8, 0));int jud(int n,vector<vector<int> > a)//??
{int sum1=0,sum2=0;for(int i=0;i<n;i++){sum1=0;sum2=0;for(int j=0;j<n;j++){sum1+=a[i][j];sum2+=a[j][i];
//行和为1,列和为1// printf("##??--%d%d%dn%dj%d-\n",i,sum1,sum2,n,j) ;if(a[i][j]==1){for(int k=0;k<n;k++){if(i+j-k<n&&i+j-k>=0&&i+j-k!=i){if(a[i+j-k][j]==a[i][j]){return false;}}if(k+j-i<n&&k+j-i>=0&&k!=i){if(a[k][k+j-i]==a[i][j]){return false;}}}}else if (a[i][j]!=0) {return false;}// printf("#--%d%d%d-\n",i,sum1,sum2) ;}if(sum1!=1||sum2!=1) {return false;}}
return true;}
int main()
{
int n1=8;
int ins;
int b[n1][n1];
//printf("%d %d",bool(true),bool(false));for(int i=0;i<n1;i++)for(int j=0;j<n1;j++){scanf("%d",&ins);a[i][j]=ins;}
//printf("%d",jud(n1,a));
if(jud(n1,a))printf("YES"); else printf("NO");
}
事实上答案只用了1-D数组(1的单坐标),并且遍历比我少一半(j>i)即可,减少重复
#include <iostream>
#include <vector>
#include <cmath>using namespace std;bool isValidQueenPlacement(const vector<vector<int>>& board) {int n = board.size();vector<int> positions(n, -1); // positions[i] 表示第 i 行的皇后所在的列// 遍历棋盘,找出所有皇后的位置for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (board[i][j] == 1) {positions[i] = j;}}}// 检查皇后之间的冲突for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {// 检查是否有两个皇后在同一列if (positions[i] == positions[j]) {return false;}// 检查是否有两个皇后在同一对角线上if (abs(positions[i] - positions[j]) == abs(i - j)) {return false;}}}return true;
}int main() {vector<vector<int>> board = vector<vector<int>>(8, vector<int>(8, 0));for (int i = 0; i < 8; i++) {for (int j = 0; j < 8; j++) {cin >> board[i][j];}}cout << (isValidQueenPlacement(board) ? "YES" : "NO") << endl;
判断这里也巧用绝对值
不过他没有判断皇后同行,似乎是包含在这两个之中了。?
N皇后
·和全排列一样,需要使用hashtable记录某个数字是否被使用
这个错代码看了好多遍了,愣是没发现错在哪
#include <iostream>
#include <vector>
#include <cmath>using namespace std;
const int N=9;
vector<vector<int> > a;
vector<int> temp;
int hashe1[N+2]={0};
void p(int index,int n)
{if (index==n){printf("?");a.push_back(temp);}for(int i=1;i<n;i++){if(hashe1[i]==0)for (int j=0;j<index;j++){temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back(); }}}//}
int main()
{int n=8;
p(0,n);printf("%d",a.size());
}
,对比我自己上次写的全排列,才发现是循环多套了一层。构造排列之后直接判断+pushback还原现场一系列操作即可,但是你却多搞了个j从1-n?
改了还是错
#include <iostream>
#include <vector>
#include <cmath>using namespace std;
const int N=9;
vector<vector<int> > a;
vector<int> temp;
int hashe1[N+2]={0};
void p(int index,int n)
{if (index==n){printf("?");a.push_back(temp);}for(int i=1;i<n;i++){if(hashe1[i]==0){temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back(); }}
}//}
int main()
{int n=8;
p(0,n);printf("%d",a.size());
}
艹!少了个等于!i从1~n,我写的i<n...
#include <iostream>
#include <vector>
#include <cmath>using namespace std;
const int N=9;
vector<vector<int> > a;
vector<int> temp;
int hashe1[N+2]={0};
void p(int index,int n)
{if (index>n-1){printf("?");a.push_back(temp);}for(int i=1;i<=n;i++){if(hashe1[i]==0){temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back(); }}
}//}
int main()
{int n=8;
p(0,n);printf("%d",a.size());
}
这下至少构造排列部分对了
然后输出还是0,崩了
#include <iostream>
#include <vector>
#include <cmath>using namespace std;
const int N=9;
vector<vector<int> > a;
vector<int> temp;
int hashe1[N+2]={0};
bool flag=0;
//bool j(vector<int> a)
//{
// for(int i=0;i<a.size();i++)
// {//不用判断同行同列,因为造出了是排列
// for(int j=i+1;i<a.size();j++)
// {
// if(abs(a[j]-a[i])==j-i) return false;
// }
// }
// return true;
// }
void p(int index,int n)
{if (index==n){a.push_back(temp);return;}for(int i=1;i<=n;i++){if(hashe1[i]==0){if(index==0){temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back();}else{//printf("?");
// flag=0;for(int k=0;k<index;k++){//printf("**%d %d %d %d.\n",k,index,temp[k],i);if(abs(i-temp[k])==abs(index-k)) {//printf("*%d %d %d %d.\n",k,index,temp[k],i);flag=1;break;}}if(!flag){//printf("**");temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back();}}}}}//}
int main()
{int n=8;
p(0,n);printf("%d",a.size());
}
竟是因为少了个flag归零。蹦
#include <iostream>
#include <vector>
#include <cmath>using namespace std;
const int N=9;
vector<vector<int> > a;
vector<int> temp;
int hashe1[N+2]={0};
bool flag=0;
//bool j(vector<int> a)
//{
// for(int i=0;i<a.size();i++)
// {//不用判断同行同列,因为造出了是排列
// for(int j=i+1;i<a.size();j++)
// {
// if(abs(a[j]-a[i])==j-i) return false;
// }
// }
// return true;
// }
void p(int index,int n)
{if (index==n){a.push_back(temp);return;}for(int i=1;i<=n;i++){if(hashe1[i]==0){if(index==0){temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back();}else{//printf("?");flag=0;//这句话害我浪费一个晚上for(int k=0;k<index;k++){//printf("**%d %d %d %d.\n",k,index,temp[k],i);if(abs(i-temp[k])==abs(index-k)) {//printf("*%d %d %d %d.\n",k,index,temp[k],i);flag=1;break;}}if(!flag){//printf("**");temp.push_back(i);hashe1[i]=1;p(index+1,n);hashe1[i]=0;temp.pop_back();}}}}}//}
int main()
{int n=8;
p(0,n);printf("%d",a.size());
}
这篇关于递归【1】(全排列andN皇后)(排列型回溯)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!