2022年1月13日学习总结

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等函数还需多加学习,加油💪(ง •_•)ง

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值