初学者的我依旧觉得难得DFS 第一题 Oil Deposits 第二题 放苹果 第三题N皇后问题

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid. 

Input

The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket. 

Output

For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets. 

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0 

Sample Output

0
1
2
2

翻译:

GeoSurvComp地质调查公司负责检测地下石油储量。GeoSurvComp一次与一个大的矩形区域一起工作,并创建一个网格,将土地划分为多个方形图。然后,它使用传感设备分别分析每个图,以确定该图是否含有油。含有油的地块称为口袋。如果两个口袋相邻,则它们是相同油藏的一部分。油沉积物可能非常大并且可能包含许多口袋。您的工作是确定网格中包含多少不同的油藏。 

输入

输入文件包含一个或多个网格。每个网格都以包含m和n的行开头,即网格中的行数和列数,由单个空格分隔。如果m = 0,则表示输入结束; 否则1 <= m <= 100并且1 <= n <= 100.此后是m行,每行n个字符(不计行行尾字符)。每个字符对应一个图,并且是“*”,表示没有油,或“@”,表示油口袋。 

产量

对于每个网格,输出不同的油藏数量。如果它们在水平,垂直或对角线上相邻,则两个不同的口袋是同一油层的一部分。油藏不得超过100个口袋。 

这一题的思路就是运动dfs和循环 然后判断八个方向是否都存在口袋,然后存在口袋将‘@’替换为‘!’符号,然后一直递归下去 直到周围八个方向没有口袋。

重点就是把相邻的口袋全部都标记成非@得字符串 然后继续进行循环找下一个口袋。

代码如下

#include <bits/stdc++.h>
using namespace std;
char str[101][101];//存图 
int n,m,sum;//sum为了记录多少油藏 
void dfs(int x,int y)
{
	if(str[x][y]!='@'|| x < 0 || y < 0 || x >= n || y >= m)//判断不是口袋的条件 
	return;
	else
	{
		str[x][y]='!' ;//将发现相邻的口袋标记 
		dfs(x+1,y);//八个方向 
		dfs(x+1,y+1);
		dfs(x,y+1);
		dfs(x-1,y);
		dfs(x-1,y-1);
		dfs(x,y-1);
		dfs(x-1,y+1);
		dfs(x+1,y-1);
	}
 }
 int main()
 {
 	while(scanf("%d%d",&n,&m)!=EOF&&m)//输入 
 	{
 		sum=0;//每次循环都将sum初始化 
 		for(int i=0;i<n;i++)
 		{
 			scanf("%s",str[i]);
		 }
		 for(int i=0;i<n;i++)
		 {
		 	for(int j=0;j<m;j++)
		 	{
		 		if(str[i][j]=='@')
		 		{
		 			sum++;//记录发现的每一个口袋并且将周围相邻口袋全部标记 
		 			dfs(i,j);
				 }
			 }
		 }
		 printf("%d\n",sum);
}
 }

放苹果

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8

这一题考虑两种情况

第一种情况是m<n的时候,这个时候有空的盘子 这就意味着盘子根本用不完,多余的盘子没什么用处 因为交换位置的次数不会增加,就相当于比如m=3,n=5,最多就会用到3个盘子也就是1 1 1 0 0或者0 0 1 1 1所以dfs(3,5)和dfs(3,3)是一样的所以dfs(m,n)=dfs(m,m)

第二种情况就是m>=n的时候,这个时候就想两种情况 就是剩下一个盘子不用的所有情况+所有盘子都用的情况,剩下一个盘子不用的所有情况是dfs(m,n-1),所有盘子的情况就比较的特殊也就是 所有盘子肯定至少有一个苹果这个时候的苹果数目就是m-n,这个时候的种类等于dfs(m-n,n);所有dfs(m,

n)=dfs(m-n,n)+dfs(m,n-1)

因此呢 用递归的出路就是苹果数量为1或者为0,或者盘子数量为1

然后看具体的代码

#include <cstdio>
using namespace std;
int ans,m,n;
int dfs(int m,int n)
{
	if(m==1||m==0||n==1) //当苹果数量为0或者1或者盘子数量的时候种类加一 
	{
		ans++;
	}
	else
	{
		if(m<n)
		{
			return dfs(m,m);//盘子数量多于苹果 
		}
		else if(m>=n)
		{
			return dfs(m-n,n)+dfs(m,n-1);//苹果数量多于盘子 
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		ans=0;
		scanf("%d%d",&m,&n);
		dfs(m,n);
		printf("%d\n",ans);
	}
}

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 
你的任务是,对于给定的N,求出有多少种合法的放置方法。 
 

Input

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input

1
8
5
0

Sample Output

1
92
10

这一题的思路就是一个一个的判断然后对成功的进行标记,然后需要注意的是可以用一维数组进行存放因为每一行不可能存在相同的皇后 所有每一行都会存在当且仅当一个皇后所有可以定义数组map【10】  然后i表示行列第几个

然后还有一个判断斜下方的是否有皇后的代码

(map[k]-map[j])==(k-j)||(map[k]-map[j])==(j-k)

然后完整的代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n,ans;
int map[15];//存图记录下想应的位置 
int visit[15];//标记 
int sol[15];//记录有多少方法 
void dfs(int k)
{
	int i,j,flag;
	if(k==n+1)//判断结束的条件 
	{
		ans++;
		return;
	}
	for(i=1;i<=n;i++)//进行n次的循环 
	if(!visit[i])  
	{
		map[k]=i;
		flag=1;
		for(j=1;j<=k-1;j++)  
		if((map[k]-map[j])==(k-j)||(map[k]-map[j])==(j-k))//判断45度斜方向的 
		{
			flag=0;
			break;
		}
		if(flag)//满足条件继续进行dfs循环 
		{
			visit[i]=1;
			dfs(k+1);//对下一个进行标记 
			visit[i]=0;  //将这个地方标记 
		}
	}
}
int main()
{
	int i;
	for(i=1;i<=10;i++)
	{
		ans=0;
		n=i;
		memset(map,0,sizeof(map));//每次都对相应的map数组清零 
		memset(visit,0,sizeof(visit));//同上 
		dfs(1);
		sol[i]=ans;//存下i从1到10的所有方法 
	}
	while(scanf("%d",&n),n)
	printf("%d\n",sol[n]);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值