枯木逢春不在茂,年少且惜镜边人
因为马上要开学了,所以准备复习算法,并且做一做题
下周----------bfs dfs 动态规划 高精加法 高精阶乘 等等等等 ,最后总结一下[滑稽]
首先看看八皇后
一个如下的
6×66 \times 6
6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列
2 4 6 1 3 52\ 4\ 6\ 1\ 3\ 5
2 4 6 1 3 5 来描述,第
ii
i 个数字表示在第
ii
i 行的相应位置有一个棋子,如下:
行号
1 2 3 4 5 61\ 2\ 3\ 4\ 5\ 6
1 2 3 4 5 6
列号
2 4 6 1 3 52\ 4\ 6\ 1\ 3\ 5
2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前
33
3 个解。最后一行是解的总个数。
输入格式
一行一个正整数
nn
n,表示棋盘是
n×nn \times n
n×n 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
6
输出
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
说明/提示
【数据范围】
对于
100%100%
100% 的数据,
6≤n≤136 \le n \le 13
6≤n≤13。
题目翻译来自NOCOW。
USACO Training Section 1.5
接下来请看代码
#include<stdio.h>
int a[105],r[105],l[105],ans[105],n,sum;
void dfs(int i)
{
int j;
if(i>n)
{
sum++;
if(sum>3)
return ;
for(i=1;i<=n;i++)
printf("%d ",ans[i]);
printf("\n");
return ;
}
for(j=1;j<=n;j++)
{
if(!a[j]&&!r[j+i]&&!l[j-i+n])
{
ans[i]=j;
a[j]=1;
r[j+i]=1;
l[j-i+n]=1;
dfs(i+1);
a[j]=0;
r[j+i]=0;
l[j-i+n]=0;
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d",sum);
return 0;
}
其实我一开始想的就是标价他的左下和下面和右下,然后不断的进行搜索,但是写了一下发现出来是乱码,看了看别人的思想,发现自己有点小问题
首先我的思想大体没有问题,但是在进行
dfs(i+1)
这个东西的时候就已经进行换列了,所以没必要进行列标记,所以要进行行标记也就是
a[i]=1;
**之后便是右下和左下了,看了个很厉害的表示
因为对角线有这样一个规则
左对角线 \
有这样的规律
y-x=常数;
但是在x>y 的时候有会是负数那怎么办?
就平移n个单位 同时在if判断的时候也就要平移
所以不会产生错误
那么右对角线 /
是
x+y=常数
这样标记三处后 然后进行搜索然后进行输出就好了
最后别忘记 回溯哦~**
下面看看连通块问题
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
输入:
11110
11010
11000
00000
输出: 1
输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
下面请看代码
#include<stdio.h>4
int map[4][5]={{1,1,1,1,0},{1,1,0,1,0},{1,1,1,0,0},{0,0,0,0,0}};
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int book[4][5];
int num;
void dfs(int x,int y,int color)
{
int k,tx,ty;
map[x][y]=color;
for(k=0;k<=3;k++)
{
tx=x+next[k][0];
ty=y+next[k][1];
if(tx>=4||tx<0||ty>=5||ty<0)
continue;
if(book[tx][ty]==0&&map[tx][ty]==1)
{
book[tx][ty]=1;
dfs(tx,ty,color);
}
}
return ;
}
int main()
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
{
if(map[i][j]==1)
{
num--;
book[i][j]=1;
dfs(i,j,num);
}
}
}
printf("%d",-num);
return 0;
}
答案是一 是对的;
这里因为力扣不会用就写了个样例子
这里通过对每一块区域进行染色,num–从而更简洁的写出他有几块区域
for(k=0;k<=3;k++)
{
tx=x+next[k][0];
ty=y+next[k][1];
if(tx>=4||tx<0||ty>=5||ty<0)
continue;
if(book[tx][ty]==0&&map[tx][ty]==1)
{
book[tx][ty]=1;
dfs(tx,ty,color);
}
}
这个部分是dfs的核心代码
另外另一组案例是这样的
int map[4][5]={{1,1,0,0,0},{1,1,0,0,0},{0,0,1,0,0},{0,0,0,1,1}};
输出结果
下面看看全排列,和组合
题目:
已知 nnn 个整数 x1,x2,…,xnx_1,x_2,…,x_nx1,x2,…,xn,以及111个整数kkk(k<nk<nk<n)。从nnn个整数中任选kkk个整数相加,可分别得到一系列的和。例如当n=4,k=3n=4,k=3n=4,k=3,444个整数分别为3,7,12,193,7,12,193,7,12,19时,可得全部的组合与它们的和为:
3+7+12=223+7+12=223+7+12=22
3+7+19=293+7+19=293+7+19=29
7+12+19=387+12+19=387+12+19=38
3+12+19=343+12+19=343+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=293+7+19=293+7+19=29。
键盘输入,格式为:
n,kn,kn,k(1≤n≤20,k<n1 \le n \le 20,k<n1≤n≤20,k<n)
x1,x2,…,xn(1≤xi≤5000000)x_1,x_2,…,x_n (1 \le x_i \le 5000000)x1,x2,…,xn(1≤xi≤5000000)
屏幕输出,格式为: 111个整数(满足条件的种数)
数据
4 3
3 7 12 19
输出
1
#include<stdio.h>
int book[21];
int f(int a)
{ int i;
for(i=2;i<a;i++)
{
if(a%i==0)
break;
}
if(a==i)
return 1;
else
return 0;
}
int n,k;
int a[25];
int b[25];
long long ans=0;
void dfs(int m,int sum,int p)
{
int i;
if(m==k)
{
if(f(sum))
ans++;
return ;
}
for(i=p;i<n;i++)
{
book[i]=1;
dfs(m+1,sum+a[i],i+1);
book[i]=0;
}
return ;
}
int main()
{ int i;
scanf("%d %d",&n,&k);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
dfs(0,0,0);
printf("%d",ans);
}
最后看看最短路径(迷宫问题)
#include <stdio.h>
int max=1000;
int p,q,min=999999999,n,m;
int book[51][51],a[51][51];
void dfs(int x,int y,int step)
{
int next[4][2]=
{
{0,1}, //向右走
{1,0}, //向下走
{0,-1}, //向左走
{-1,0} //向山走
};
int tx,ty;
//判断是否到达小哈的位置
if (x==p&&y==q) {
//更新最小值
if(step<min)
min=step;
return;
}
//枚举4种走法
for (int k=0; k<=3; k++) {
//计算下一个点的坐标
tx=x+next[k][0];
ty=y+next[k][1];
//判断是否越界
if(tx<1||tx>n||ty<1||ty>m)
continue;
//判断该点是否为障碍物或者已经在路径中
if (a[tx][ty]==0&&book[tx][ty]==0) {
book[tx][ty]=1; //标记这个点已经走过
dfs(tx, ty, step+1); //尝试下一个点
book[tx][ty]=0; //尝试结束,取消这个点的标记
}
}
}
int main() {
int startx,starty;
scanf("%d %d",&n,&m); //n行m列
//读入迷宫
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
//读入起点坐标和终点坐标
scanf("%d %d %d %d",&startx,&starty,&p,&q);
//从起点开始搜索
book[startx][starty]=1; //标记起点已经在路径,防止后面重复走
dfs(startx, starty, 0);
printf("%d\n",min);
return 0;
}
最短路径其实就是dfs bfs的最初等的模板
好了下周复习背包 高精 还有序列,顺便做些题目。