周报(算法复习,加学习)

枯木逢春不再茂,年少且惜镜子边人

这周准备复习一下之前的内容,学习一下图,和树(简单的),然后学习一下java操作,然后做一些题.(想法很好)
1.先来说说学过的,栈和队列吧
栈 是先进后出
队列是 先进先出
写一个例子(队列!)吧
首先题目,一串数字,一个删除第二个放最后,然后第3个删除 第4个放最后,依次进行,然后输出删除的就是需要的东西,来看看吧

#include<stdio.h>
int main()
{
 int q[102]={0,6,3,1,7,5,8,9,2,4},head,tail;
 head=1;
 tail=10;
 while(head<tail)
 {
  printf("%d",q[head]);
  head++;
  q[tail]=q[head];
  tail++;
  head++;
  
 }
 return 0;
}

然后用结构体写一遍吧

#include<stdio.h>
struct que
{
 int data[1000];
 int head;
 int tail;
};
int main()
{
 struct que q;
 int i;
 que.tail=1;
 que.head=1;
 for(i=1;i<=9;i++)
 {
  scanf("%d",&q.data[tail]);
  q.tail++;
 }
 whie(q.head<q.tail)
 {
  printf("%d",q.data[q.head]);
  q.head++;
  q.data[q.tail]=q.data[q.head];
  q.tail++;
  q.head++;
 }
 return 0;
}

基本操作,大家都可以看懂吧.
下来讲一下栈吧
栈的特例就是回文判断
多的不说了,直接看代码吧!

#include<stdio.h>
#include<string.h>
int main()
{
 char a[101],s[101];
 int i,len,mid,next,top;
 gets(s);
 len=strlen(s);
 mid=len/2-1;
 top=0;
 for(i=0;i<=mid;i++)
 a[++top]=s[i];
 if(len%2==0)
 next=mid+1;
 else
 next=mid+2;
 for(i=next;i<len;i++)
 {
  if(s[i]!=a[top])
  break;
  top--;
 }
 if(top==0)
 printf("yes");
 else
 printf("no");
 return 0; 
}

这样判断回文就很简单
看一下结构体中的栈吧

#include<stdio.h>
#include<string.h>
struct zhan
{
 char s[101];
 int top;
};
int mian()
{
 int len,mid,next,i;
 char a[101]; 
 struct zhan f;
 gets(a);
 f.top=0;
 len=strlen(a);
 mid=mid/2-1;
 for(i=0;i<=mid;i++)
 f.s[++top]=a[i];
 if(len/2==0)
 next=mid+1;
 else
 next=mid+2
 for(i=next;i<len;i++)
 {
  if(f.s[top]!=a[i])
  break;
  s.top--;
 } 
 if(s.top==0)
 printf("YES");
 else
 printf("no");
 return 0;
}

史诗级大题《马拦过河卒》
棋盘上 AAA 点有一个过河卒,需要走到目标 BBB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CCC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,AAA 点 (0,0)(0, 0)(0,0)、BBB 点 (n,m)(n, m)(n,m),同样马的位置坐标是需要给出的。

现在要求你计算出卒从 AAA 点能够到达 BBB 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式 一行四个正整数,分别表示 BBB 点坐标和马的坐标。
输出格式 一个整数,表示所有的路径条数。
输入输出样例 输入 #1
复制
6 6 3 3
输出 #1
复制
6
说明/提示 对于 100%100 %100% 的数据,1≤n,m≤201 \le n, m \le 201≤n,m≤20,0≤0 \le0≤ 马的坐标 ≤20\le 20≤20。

#include<stdio.h>
long long dp[21][21]={1};
int next[2][9]={{0,-2,-1,1,2,2,1,-1,-2},{0,1,2,2,1,-1,-2,-2,-1}};
int book[21][21];
int main()
{
 int i,j;
 int bx,by,mx,my;
 scanf("%d%d%d%d",&bx,&by,&mx,&my);
 for(i=0;i<9;i++)
 {
  if(mx+next[0][i]>=0&&mx+next[0][i]<=bx&&my+next[1][i]>=0&&my+next[1][i]<=by)
  book[mx+next[0][i]][my+next[1][i]]=1;
 }
 for(i=0;i<=bx;++i)
  for(j=0;j<=by;++j)
  {
   if(i)
   dp[i][j]+=dp[i-1][j];
   if(j)
   dp[i][j]+=dp[i][j-1];
   dp[i][j]=dp[i][j]*(!book[i][j]);
  }
 printf("%lld",dp[bx][by]);
 return 0;
}

递推公式就dp[i][j]这个点会有两条路,一个上面,一个左边,dp代表的是这个点有几条路经过,所以递推公式就 dp[i][j]=dp[i-1][j]+dp[i][j-1];
然后把马的那几个点标记,标记时,标记终点以内的点。这样就可以了,详细请看代码!

重磅大题
《高精乘法,高精加法》
例题: 阶乘

#include<stdio.h>
int max=101;
int a[202],b[202],n,x;
int main()
{
 int i,j,z;
 a[0]=b[0]=1;
 scanf("%d",&n);
 for(i=2;i<=n;i++)
 {
  for(j=0;j<=max;j++)//模拟阶乘,如果是大于二位,则是模拟乘法
  b[j]=b[j]*i;
  for(j=0;j<=max;j++)
  {
   if(b[j]>=10)//进位
   {
    b[j+1]+=b[j]/10;
    b[j]=b[j]%10;
   }
  }
  for(z=0;z<=max;z++)//高精加法
  {
   a[z]+=b[z];//累加的结果
   if(a[z]>=10)//进位
   {
    a[z+1]+=a[z]/10;
    a[z]%=10;
   }
  }
 }
 for(i=202;i>=0;i--)
 if(a[i]!=0)
 {
 x=i;
 break;
    }
    for(j=x;j>=0;j--)
    printf("%d",a[j]);
    printf("\n");
    return 0;
}

这是我目前看到的最简单的高精算法了,很棒,如有大佬有更简单的,请给小弟指出,QQ:**********,谢谢大佬

相信大家都知道炸弹人游戏吧,今天用dfs和bfs来做一做

#include<stdio.h>
struct node
{
 int x;
 int y;
};
struct node que[401];
char a[20][21];
int book[20][21];
int getnum(int i,int j)
{
 int sum=0,tx,ty;
 tx=i;ty=j;
 while(a[tx][ty]!='#')
 {
  if(a[tx][ty]=='G')
  sum++;
  tx--;
 }
 tx=i;ty=j;
 while(a[tx][ty]!='#')
 {
  if(a[tx][ty]=='G')
  sum++;
  tx++;
 }
 tx=i;ty=j;
 while(a[tx][ty]!='#')
 {
  if(a[tx][ty]=='G')
  sum++;
  ty--;
 }
 tx=i;ty=j;
 while(a[tx][ty]!='#')
 {
  if(a[tx][ty]=='G')
  sum++;
  ty++;
 }
 return sum;
}
int main()
{
 int i,head,tail,tx,ty,mx,my,max=0,startx,starty,m,n,k;
 int next[4][2]={{0,1},{1,0},{0-1},{-1,0}};
 int sum=0;
 scanf("%d %d %d %d",&m,&n,&startx,&starty);
 for(i=0;i<m;i++)
 scanf("%s",a[i]);
 head=1;
 tail=1;
 que[tail].x=startx;
 que[tail].y=starty;
 max=getnum(startx,starty);
 tx=startx;
 ty=starty;
 book[tx][ty]=1;
 tail++;
 while(head<tail)
 {
  for(k=0;k<4;k++)
  {
   tx=que[head].x+next[k][0];
   ty=que[head].y+next[k][1];
   if(tx<0||tx>n-1||ty<0||ty>m-1)
   continue;
   if(a[tx][ty]=='.'&&book[tx][ty]==0)
   {
    book[tx][ty]=1;
    que[tail].x=tx;
    que[tail].y=ty;
    tail++;
    sum=getnum(tx,ty);
    if(sum>max)
    {
     max=sum;
     mx=tx;
     my=ty;
    }
      }
  }
 head++;
 }
  printf("应该放在(%d,%d)处,消灭了%d个敌人",mx,my,max);
  return 0;
 
}

getnum函数是统计在这个点周围一共有多少敌人,依次上下左右寻找敌人
其他的则就是普通的bfs
再来看看dfs如何解决这道题吧

#include<stdio.h>
char map[20][21];
int book[20][21];
int next[4][2]={{0,1},{1,0},{0-1},{-1,0}};
int tx,ty,max,sum,mx,my,n,m;
int getnum(int i,int j)
{
 int sum=0,tx,ty;
 tx=i;ty=j;
 while(map[tx][ty]!='#')
 {
  if(map[tx][ty]=='G')
  sum++;
  tx--;
 }
 tx=i;ty=j;
 while(map[tx][ty]!='#')
 {
  if(map[tx][ty]=='G')
  sum++;
  tx++;
 }
 tx=i;ty=j;
 while(map[tx][ty]!='#')
 {
  if(map[tx][ty]=='G')
  sum++;
  ty--;
 }
 tx=i;ty=j;
 while(map[tx][ty]!='#')
 {
  if(map[tx][ty]=='G')
  sum++;
  ty++;
 }
 return sum;
}
int dfs(int x,int y)
{
 int k;
 sum=getnum(x,y);
 if(sum>max)
 {
  max=sum;
  mx=x;
  my=y;
 }
 for(k=0;k<4;k++)
 {
  tx=x+next[k][0];
  ty=y+next[k][1];
  if(tx<0||tx>n-1||ty<0||ty>m-1)
  continue;
  if(map[tx][ty]=='.'&&book[tx][ty]==0)
  {
   book[tx][ty]=1;
   dfs(tx,ty);
  }
 }
 return 0;
}
int main()
{
 int i,startx,starty;
 scanf("%d %d %d %d",&n,&m,&startx,&starty);
 for(i=0;i<n;i++)
 scanf("%s",map[i]);
 max=getnum(startx,starty);
 mx=startx;
 my=starty;
 dfs(startx,starty);
 printf("应该放在(%d,%d)处,消灭了%d个敌人",mx,my,max);
}

在这里插入图片描述dfs和bfs都可以解决这道题,宽搜是从一个点扩展出4个点然后依次计算4个点,然后继续搜索,dfs是一条路线,搜索不下去了然后就退回来,因为之前标记过,所以就不会算重复的点,感觉就是不撞南墙不回头的样子,更多请看代码
下面就来看一下,之前林某人讲过的判断面积吧
题目:一张地图中判断岛屿
话不多说看代码

#include<stdio.h>
struct node
{
	int x;
	int y;
};
int book[51][51];
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; 
int main()
{
	int i,j,m,n,startx,starty,tx,sum=0,ty,k;
	struct node que[2501];
	int a[51][51];
	int head,tail; 
	scanf("%d %d %d %d",&n,&m,&startx,&starty);
	for(i=1;i<=n;i++)
	 for(j=1;j<=m;j++)
	 scanf("%d",&a[i][j]);
	head=1;tail=1;
	que[tail].x=startx;
	que[tail].y=starty;
	book[startx][starty]=1;
	sum=1;
	tail++;
	while(head<tail)
	{
		for(k=0;k<4;k++)
		{
			tx=que[head].x+next[k][0];
			ty=que[head].y+next[k][1];
			if(tx<1||tx>n||ty<1||ty>m)
			continue;
			if(a[tx][ty]!=0&&book[tx][ty]==0)
			{
				sum++;
				book[tx][ty]=1;
				que[tail].x=tx;
				que[tail].y=ty;
				tail++;
			}
		}
		head++;
	}
	printf("%d\n",sum);
	return 0;
}

这道题可以用BFS DFS都可以做,和传统的模板没什么太大区别,我们看看dfs吧
在这里插入图片描述

#include<stdio.h>
int a[51][51];
int book[51][51];
int n,m,tx,ty,sum;
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
void dfs(int x,int y)
{
	int k;
	for(k=0;k<4;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)
		{
			sum++;
			book[tx][ty]=1;
			dfs(tx,ty);
		}
	}
	return ;
}
int main()
{
	int startx,starty,i,j;
	scanf("%d %d %d %d",&n,&m,&startx,&starty);
	for(i=1;i<=n;i++)
	 for(j=1;j<=m;j++)
	scanf("%d",&a[i][j]);
	sum=1;
	book[startx][starty]=1;
	dfs(startx,starty);
	printf("%d\n",sum);
	return 0;
}

这就是用dfs做的找地图题,很基础的,基本套用模板
接下来就是判断有一张地图里面有几张这样的岛屿了(这其中暗藏了染色),话不多说直接看代码吧!

#include<stdio.h>
int tx,ty,n,m,num=0;
int a[51][51];
int book[51][51];
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
void dfs(int x,int y,int color)
{
	int k;
	a[x][y]=color;
	for(k=0;k<4;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,color);
		}
	}
	return ;
}




int main()
{
	int i,j,startx,starty;
	scanf("%d %d %d %d",&n,&m,&startx,&starty);
	for(i=1;i<=n;i++)
	 for(j=1;j<=m;j++)
	scanf("%d",&a[i][j]);
	for(i=1;i<=n;i++)
	 for(j=1;j<=m;j++)
	 {
	 	if(a[i][j]>0)
	 	{
	 		book[i][j]=1;
	 		num--;
	 		dfs(i,j,num);
		}
	 }
	for(i=1;i<=n;i++)
	 {
	 for(j=1;j<=m;j++)
	 printf("%3d",a[i][j]);
	 printf("\n");
	 } 
	 printf("共有%d个岛屿",-num);
}

多加了个参数color,进行染色,主要部分还是搜索一个地图,
在这里插入图片描述这就是染色问题
哎这周还是没有达到理想要求,但是搜索基本算入门,还有个水管工问题没有解决,放在下次周报吧。好的,谢谢各位大佬围观,下周见。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值