0
点赞
收藏
分享

微信扫一扫

蓝桥杯入门听课笔记

Sky飞羽 2022-03-11 阅读 78
#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;
}





 






举报

相关推荐

0 条评论