#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
/*
int a
a = 1.0 ; //结果转为 1
-------------------------
输入一行字符有空格 cout<< 不行 用 gets(s) 但是 这是char型的 ! C语言的 ,不是c++的string型
string型
可以 string s ; s[i] 读取到 s.size()
while(cin>>s[num])num++
int len = s[num - 1].length
质因数分解 m = 质因数*质因数*质因数... (质因数 2 3 5 7 )
for int i = 2 -- > n/2 t % i
-------
填空题 枚举 输入答案即可 万能头 #include<bits/stdc++>
如 2019 = ?+?+? 且 3个数相同,在不同位置属于一种 ,即不排列,
可以用 a > b > c;
--------------------
既约分数有多少个 蛇形填数(模拟)
用set排列去重
EOF 读到文件结束位置 ,Ctrl + Z 再回车
vis 状态数组 选或不选 ---- 1 / 0
全排列
vis 用过的数标记为1
简单斐波那契
dfs 八皇后 再看
int xx{-1,0,1,0}
int yy{0,1,0,-1}
dx = dx + xx[i] , dy = dy + yy[i] //等效上下左右 遍历搜索找通路 dfs() 最后写结束条件
*/
int f(int n ) { // f(0) 时return 打印顺序 f (1) 中的 cout<< n << " " 执行(递归)完才f(2)中的执行 ...f(n) 的最后执行
if(n == 0)return 1;
f(n - 1);
cout<< n << " ";
}
void test_t() {
f(9);//1 2 3 4 5 6 7 8 9
}
/*
int search(int t)
{
if(满足输出条件)
{
输出解;
}
else
{
for(int i=1;i<=尝试方法数;i++)
if(满足进一步搜索条件)
{
为进一步搜索所需要的状态打上标记;
search(t+1);
恢复到打标记前的状态;//也就是说的{回溯一步}
}
}
}
*/
//1 -- n 的全排列
//dfs思想
int n;
int ans[20];
int vis[20]; //标记数组
void dfs(int step) { // step,表示 1 - 3 个位置
if(step == n + 1) { //出口 打印全排列 此语句 先执行,所以填满的时候(一轮排列完) step == n+1
for(int i = 1; i <= n; i++) //n个数
cout<< ans[i] <<" ";
cout<<endl;
}
for(int i = 1; i <= n; i++) { // 每轮 遍历填满 n个数 每个数都被使用 由于每次递归的step不同(起始位置不同) 每次打印的排列就不同
if(vis[i] == 0) { //i位置未使用过
ans[step] = i; //位置等于i
vis[i] = 1; //标记位置已经使用
dfs(step + 1); //从1位置开始 递归到结束
vis[i] = 0; //标记数组清0 ,否则都标记过了,只输出一次
}
}
}
//洛谷题解
/*
include<iostream>//个人建议不使用万能头文件,如果要使用万能头文件,就不能定义数组map;
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
int map[6][6];//地图;
bool temp[6][6];//走过的标记;
int dx[4]={0,0,1,-1};//打表;
int dy[4]={-1,1,0,0};//打表;
int total,fx,fy,sx,sy,T,n,m,l,r;//total计数器,fx,fy是终点坐标,sx,sy是起点坐标,T是障碍总数,n,m是地图的长和宽,l,r是障碍的横坐标和纵坐标;
void walk(int x,int y)//定义walk;
{
if(x==fx&&y==fy)//fx表示结束x坐标,fy表示结束y坐标;
{
total++;//总数增加;
return;//返回,继续搜索;
}
else
{
for(int i=0;i<=3;i++)//0——3是左,右,下,上四个方向;
{
if(temp[x+dx[i]][y+dy[i]]==0&&map[x+dx[i]][y+dy[i]]==1)//判断没有走过和没有障碍;
{
temp[x][y]=1;//走过的地方打上标记;
walk(x+dx[i],y+dy[i]);
temp[x][y]=0;//还原状态;
}
}
}
}
int main()
{
cin>>n>>m>>T;//n,m长度宽度,T障碍个数
for(int ix=1;ix<=n;ix++)
for(int iy=1;iy<=m;iy++)
map[ix][iy]=1;//把地图刷成1;
cin>>sx>>sy;//起始x,y
cin>>fx>>fy;//结束x,y
for(int u=1;u<=T;u++)
{
cin>>l>>r;//l,r是障碍坐标;
map[l][r]=0;
}
walk(sx,sy);
cout<<total;//输出总数;
return 0;
}
*/
/*
#include<bits/stdc++.h>
using namespace std;
int q[101][101];
int sum=0;
int i,j,n,m,t,sx,sy,x,y,ex,ey;
void dfs(int a,int b)
{
if (a==ex&&b==ey)//终止条件
{
sum++;
return;
}
else
{
q[a][b]=0;//保存结果
if(q[a-1][b]!=0) {dfs(a-1,b);q[a-1][b]=1;}
if(q[a][b-1]!=0) {dfs(a,b-1);q[a][b-1]=1;}
if(q[a][b+1]!=0) {dfs(a,b+1);q[a][b+1]=1;}
if(q[a+1][b]!=0) {dfs(a+1,b);q[a+1][b]=1;}//这四部是穷举所有可行的搜索,并且回溯
}
}
int main()
{
memset(q,0,sizeof(q));//边界当作障碍。 memset 把数组q 赋初始值 为0 数组范围 0- sizeof(q)(内存中实际存放的数组是连续的!)
cin>>n>>m>>t;
cin>>sx>>sy>>ex>>ey;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
q[i][j]=1;//可以走
for(i=1;i<=t;i++)
{
cin>>x>>y;
q[x][y]=0;//障碍物初始化
}
dfs(sx,sy);
cout<<sum<<endl;
return 0;
}
*/
/*
P1219 [USACO1.5]八皇后 Checker Challenge
题目描述
一个如下的 6 \times 66×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,
每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5 来描述,第 ii 个数字表示在第 ii 行的相应位置有一个棋子,如下:
行号 1\ 2\ 3\ 4\ 5\ 61 2 3 4 5 6
列号 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 33 个解。最后一行是解的总个数。
输入格式
一行一个正整数 nn,表示棋盘是 n \times nn×n 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入
6
输出
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
*/
/*
#include<iostream>//个人不建议采用头文件,可能和定义的变量或名字起冲突,从而引起编译错误;
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
int a[100],b[100],c[100],d[100];
//a数组表示的是行;
//b数组表示的是列;
//c表示的是左下到右上的对角线;
//d表示的是左上到右下的对角线;
int total;//总数:记录解的总数
int n;//输入的数,即N*N的格子,全局变量,搜索中要用
int print()
{
if(total<=2)//保证只输出前三个解,如果解超出三个就不再输出,但后面的total还需要继续叠加
{
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";//for语句输出
cout<<endl;
}
total++;//total既是总数,也是前三个排列的判断
}
void queen(int i)//搜索与回溯主体
{
if(i>n)
{
print();//输出函数,自己写的
return;
}
else
{
for(int j=1;j<=n;j++)//尝试可能的位置
{
if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))//如果没有皇后占领,执行以下程序
{
a[i]=j;//标记i排是第j个
b[j]=1;//宣布占领纵列
c[i+j]=1;
d[i-j+n]=1;
//宣布占领两条对角线
queen(i+1);//进一步搜索,下一个皇后
b[j]=0;
c[i+j]=0;
d[i-j+n]=0;
//(回到上一步)清除标记
}
}
}
}
int main()
{
cin>>n;//输入N*N网格,n已在全局中定义
queen(1);//第一个皇后
cout<<total;//输出可能的总数
return 0;
}
###注释:对角线d[i-j]后面必须加上一个n,因为i-j可能为负数,那么数组就会出错,所以将整体向右偏移n个单位(坐标偏移不会影响我们需要达到的目的),将所有可能变成正数;(因为i-j的最小值是-n+1,所以加上一个n就一定会变成一个正数)
本道题最重要的就是记录下皇后占领的格子(打标记的思想),通过此判断下一个皇后是否可以在某个位置,如果可以,则继续搜索下一个皇后可以在的位置,如果不行,则清除标记回到上一步,继续搜索;
可以先考虑六个皇后(即6*6网格),再将6改为n,并且输入n,就可以得出6到13个皇后的解了;
*/
/*P1443 马的遍历
题目描述
有一个 n \times mn×m 的棋盘,在某个点 (x, y)(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n, m, x, yn,m,x,y。
输出格式
一个 n \times mn×m 的矩阵,代表马到达某个点最少要走几步(左对齐,宽 55 格,不能到达则输出 -1?1)。
输入输出样例
输入
3 3 1 1
输出
0 3 2
3 -1 1
2 1 4
*/
/*
STL大法好!!
取百家所长成一家之言!!
介绍一下用STL模板库 <queue>来广搜这道题
广搜什么的自然不同我介绍; 我来介绍一下非常好用但没人用的
pair
queue<pair<int,int> > q;
它可以将两种数据类型的值组合成一个值存入
队列中大体是这样操作:
queue<pair<int,int> > q;//定义
q.push(make_pair(x,y));//入队
//取队首
xx=q.front().first;//第一个值
yy=q.front().second;//第二个值
q.pop();//出队
个人认为带头文件的33行代码还是很短的(>_<
*/
/*
#include<iostream>//P1443
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={2,1,-1,-2,2,1,-1,-2};//8个方向
queue<pair<int,int> > q;
int f[500][500];//存步数
bool vis[500][500];//走没走过
int main()
{
int n,m,x,y;
memset(f,-1,sizeof(f));memset(vis,false,sizeof(vis));
cin>>n>>m>>x>>y;
f[x][y]=0;vis[x][y]=true;q.push(make_pair(x,y));
while(!q.empty())
{
int xx=q.front().first,yy=q.front().second;q.pop();//取队首并出队
for(int i=0;i<8;i++)
{
int u=xx+dx[i],v=yy+dy[i];
if(u<1||u>n||v<1||v>m||vis[u][v])continue;//出界或走过就不走
vis[u][v]=true;q.push(make_pair(u,v));f[u][v]=f[xx][yy]+1;
}
}
for(int i=1;i<=n;i++)
{for(int j=1;j<=m;j++)printf("%-5d",f[i][j]);printf("\n");}//注意场宽!!
return 0;
}
*/
/* #include<stack>
stack<int>s;
栈的push pop top s.empty()
入栈 出栈 获取栈顶元素 是否为空
括号匹配 左括号入栈
'('左括号多了---> 遍历完栈非空 ,
')'右括号多了,栈为空,还未遍历完
*/
int main() {
cin>>n;
dfs(1);
// test_t();
return 0;
}