1.补全内容
dfs的模板
2.bfs的模板
ypedef struct node
{
int x,y,step;
}node;
int sx,sy,fx,fy;//起点终点坐标
int s[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//移动数组
int vis[110][110];//标记数组
int mp[110][110];//地图数组
int n,m;
int bfs()
{
queue<node> q;//定义队列
node st;
st.x=sx,st.y=sy,st.step=0;
q.push(st); //将起点放进去
vis[sx][sy]=1;//标记起点已经走过
while(!q.empty())
{
node p=q.front();
q.pop();//取出队列对头第一个元素
if(p.x==fx&&p.y==fy)
{
//终止条件到达终点,返回最小步数
return p.step;
}
for(int i=0;i<4;i++)
{
int nx=p.x+s[i][0],ny=p.y+s[i][1];
if(nx<0||ny<0||nx>=n||ny>=m||vis[nx][ny]==1||mp[nx][ny]==1)
{
//坐标超出边界,走过,不能走直接跳过
continue;
}
node yy;
yy.x=nx;
yy.y=ny;
yy.step=p.step+1;//子节点的步数是父节点步数+1
vis[nx][ny]=1;
q.push(yy);
}
}
//没有这样的路线
return -1;
}
3.快排的模板
#include <stdio.h>
#include <stdlib.h>
#define N 7
//函数dayin:打印数组元素
void dayin(int array[], int max) //max为数组元素最大值
{
for(int i = 0; i < max; i++)
{
printf("%-3d", array[i]);
}
printf("\n");
}
//函数swap交换两个数 c++里函数库有这个函数 可以直接写
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
/*quicksort 快速排序算法
对数组arr[low...high]进行快速排序,
首先进行分割操作,返回中轴元素下标 j,
然后对左数组arr[low...j-1] 和 右数组arr[j+1...high]分别递归进行排序
递归终止当然是数组大小为小于等于1(0或1)时*/
void quicksort(int array[], int max, int low, int high)
{
int i, j;
if(low < high)
{
//int v = array[low]; //中轴元素v
i = low + 1; // array[low]作为基准数(一般第一个),从array[begin+1]开始与基准数比较
j = high; // array[high]是数组的最后一位
while(i < j)
{
if(array[i] > array[low]) // 如果比较的数组元素大于基准数,则交换位置。
{
swap(&array[i], &array[j]); // 交换两个数
j--;
}
else
{
i++; // 将数组向后移一位,继续与基准数比较。
}
}
/* 跳出while循环后,i = j。
* 然后就是分割操作了
* 这个时候将数组array分成两个部分,再将array[i]与array[low]进行比较,决定array[i]的位置。
* 最后将array[i]与array[high]交换,进行两个分割部分的排序!退出条件不满足i = j
*/
if(array[i] >= array[low]) // 取等>=
{
i--;
}
swap(&array[low], &array[i]);
quicksort(array, max, low, i);
quicksort(array, max, j, high);
}
}
// 主函数
int main()
{
int array[N] = {5,2,4,3,8,7,9,};
int max = N;
printf("排序前的数组\n");
dayin(array, max);
quicksort(array, max, 0, max-1); // 快速排序
printf("排序后的数组\n");
dayin(array, max);
return 0;
}
下面是几个习题
1.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 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1复制
6
输出 #1复制
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4
说明/提示
【数据范围】
对于 100\%100% 的数据,6 \le n \le 136≤n≤13。
题目翻译来自NOCOW。
USACO Training Section 1.5
/*P1219 [USACO1.5]八皇后 Checker Challenge
#include<bits/stdc++.h>
using namespace std;
int a[14];
int cew[3][100];
int num=0,n;
void dfs(int step)
{
if(step>n){
num++;
if(num>3) return;
else{
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
return;
}
}
for(int i=1;i<=n;i++){
if(!cew[0][i]&&!cew[1][step+i]&&!cew[2][step-i+n]){
a[step]=i;//记录第line行皇后的位置
cew[0][i]=1;//标记皇后存在的列、上下对角线
cew[1][step+i]=1;
cew[2][step-i+n]=1;
dfs(step+1);//递归line+1行
cew[0][i]=0; //回溯
cew[1][step+i]=0;
cew[2][step-i+n]=0;
}
}
}
int main()
{
cin>>n;
dfs(1);
cout<<num;
return 0;
}
这个题目跟迷宫问题不太一样的是越界条件————不能同一行、一列、一个对角线上;所以我采用了一个二维数组(三行)来记录情况,用三个一维数组记录也可以,从左上到右下满足的条件为x+y为定值;而从右上到左下则满足|x-y|为定值。
而编写dfs过程大致与模板一致。
2.迷宫
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
题目描述
无
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
输入输出样例
输入 #1复制
2 2 1 1 1 2 2 1 2
输出 #1复制
1
说明/提示
【数据规模】
1≤N,M≤5
#include <stdio.h>
int mp[6][6];
int b[6][6];
int c[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
int n,m,t;
int sx,sy,fx,fy;
int sum;
void dfs(int x ,int y){
int i,tx,ty;
if(x==fx&& y==fy) ++sum;
for(i=0;i<4;i++){
tx=x+c[i][0];
ty=y+c[i][1];
if(tx<1||tx>n ||ty<1||ty>m || mp[tx][ty]==-1 || b[tx][ty]) {
continue;
}
b[tx][ty]=1;
dfs(tx,ty);
b[tx][ty]=0;
}
}
int main(){
int i,hx,hy;
sum=0;
scanf("%d %d %d",&n,&m,&t);
scanf("%d %d %d %d",&sx,&sy,&fx,&fy);
for(i=0;i<t;i++)
{
scanf("%d %d",&hx,&hy);
mp[hx][hy]=-1;
}
b[sx][sy]=1;//标记起始位置
dfs(sx ,sy);
printf("%d",sum);
return 0;
}
这个就是一个很经典的迷宫题目了,模板熟练运用即可
3.链表遍历
题目描述
小T昨天很不爽
昨天路过体彩销售点买了2注生日号码玩,当晚开奖后……
小T号码: 8902088
中奖号码:3902888
一个号码不对就差了十几万……
小T想:为什么规则是那样玩的啊……为什么5个号码要连续才能中二等奖啊……
我自己创建个规则,开N个数字,只要数字位置对了不一定要连续就可以有奖。
现在有一个中奖号码,有一个兑奖号码,小T想知道一共有多少个数字位置正确的,N太大了……
要求用链表做
输入格式
输入数据第一行包含一个整数T表示有T组测试数据
对于每组测试数据
第一行包含一个整数N,表示有N个数字
第二行包含N个中奖号码
第三行包含N个兑奖号码
输出格式
对于每组测试数据输出有多少个号码位置正确了
样例输入content_copy
2
7
3902888
8902088
10
1234567890
0987654321
样例输出content_copy
5
0
#include<stdio.h>
#include<string.h>
typedef struct a{
char node;
struct a *next;
}*LinkList,Node;
void Cerate(LinkList *L,int n)//建立链表的模板
{
LinkList p,r;
int i;
*L=(LinkList)malloc(sizeof(Node));
r=*L;
for(i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(Node));
scanf("%c",&(p->node));
r->next=p;
r=p;
}
r->next=NULL;
}
int main()
{
LinkList a,b,end;
int m,n,T,count;
char c;
while(scanf("%d",&T)!=EOF)
{
scanf("%c",&c);
while(T--)
{
count=0;
scanf("%d",&m);
scanf("%c",&c);
Cerate(&a,m);
scanf("%c",&c);
Cerate(&b,m);
scanf("%c",&c);
a=a->next;
b=b->next;
while(a!=NULL)
{
if(a->node==b->node)
{
count++;
}
a=a->next;
b=b->next;
}
printf("%d",count);
printf("\n");
}
}
}
但是弄完后还是有点懵,比如memset,malloc,typeof 广度搜索里的队列queue,push,pop等函数还需多加学习,加油💪(ง •_•)ง