首页 > 其他分享 >Part 3.1 深度优先搜索

Part 3.1 深度优先搜索

时间:2024-06-02 14:29:18浏览次数:26  
标签:优先 int ans 样例 vis Part 砝码 3.1 id

深度优先搜索(DFS),即按照深度优先的顺序搜索的算法。

深度优先搜索一般使用栈来实现。

[USACO1.5] 八皇后 Checker Challenge

题目描述

一个如下的 6 × 6 6 \times 6 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5 来描述,第 i i i 个数字表示在第 i i i 行的相应位置有一个棋子,如下:

行号 1   2   3   4   5   6 1\ 2\ 3\ 4\ 5\ 6 1 2 3 4 5 6

列号 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 3 3 个解。最后一行是解的总个数。

输入格式

一行一个正整数 n n n,表示棋盘是 n × n n \times n n×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

样例 #1

样例输入 #1

6

样例输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 6 ≤ n ≤ 13 6 \le n \le 13 6≤n≤13。

题目翻译来自NOCOW。

USACO Training Section 1.5

代码实现

#include<iostream>
using namespace std;
#define MAX_N 13
int ans[MAX_N+5];
int vis_col[MAX_N+5]={0},vis_dui1[MAX_N*2+5]={0},vis_dui2[MAX_N*2+5];
int n,cnt=0;
void dfs(int row)
{
	if(row==n+1)
	{
		cnt++;
		if(cnt<=3)
		{
			for(int i=1;i<=n;i++)
			{
				if(i!=1)cout<<" ";
				cout<<ans[i];
			}
			cout<<endl;
		}
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(vis_col[i])continue;
		if(vis_dui1[i-row+n])continue;
		if(vis_dui2[i+row-1])continue;
		vis_col[i]=1;
		vis_dui1[i-row+n]=1;
		vis_dui2[i+row-1]=1;
		ans[row]=i;
		dfs(row+1);
		vis_col[i]=0;
		vis_dui1[i-row+n]=0;
		vis_dui2[i+row-1]=0;
	}
}
int main()
{
	cin>>n;
	dfs(1);
	
	cout<<cnt;
	return 0;
 } 

[NOIP2000 提高组] 单词接龙

题目背景

注意:本题为上古 NOIP 原题,不保证存在靠谱的做法能通过该数据范围下的所有数据。

本题为搜索题,本题不接受 hack 数据。关于此类题目的详细内容

NOIP2000 提高组 T3

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastastonish,如果接成一条龙则变为 beastonish,另外相邻的两部分不能存在包含关系,例如 atatide 间不能相连。

输入格式

输入的第一行为一个单独的整数 n n n 表示单词数,以下 n n n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。

输出格式

只需输出以此字母开头的最长的“龙”的长度。

样例 #1

样例输入 #1

5
at
touch
cheat
choose
tact
a

样例输出 #1

23

提示

样例解释:连成的“龙”为 atoucheatactactouchoose

n ≤ 20 n \le 20 n≤20。

代码实现

#include<iostream>
#include<vector>
using namespace std;
#define MAX_N 20
string arr[MAX_N+5];
int to[MAX_N+5][MAX_N+5];
int cnt[MAX_N+5]={0};
vector<int>start;
int n;
int final_ans=0;
void dfs(int k,int ans)
{
	final_ans=max(final_ans,ans);
	for(int i=1;i<=n;i++)
	{
		if(to[k][i]&&cnt[i]!=2)
		{
			cnt[i]++;		
			dfs(i,ans+arr[i].size()-to[k][i]);
			cnt[i]--;
		}
	}
	return ;
}
int main()
{

	cin>>n;
	char st;
	for(int i=1;i<=n;i++)cin>>arr[i];
	cin>>st;
	for(int i=1;i<=n;i++)
	{
		if(arr[i][0]==st)start.push_back(i);
		for(int j=1;j<=n;j++)
		{
			int max_len=min(arr[i].size(),arr[j].size());
			for(int len=1;len<=max_len;len++)
			{
				int j_pos=len-1;
				int flag=1;
				int sz=arr[i].size();
				for(int k=sz-1;k>=(sz-len);k--)
				{
					if(arr[i][k]==arr[j][j_pos--])continue;
					flag=0;
					break;
				}
				if(flag)
				{
					if(len==max_len)break;
					to[i][j]=len;
					break;
				}
			}
		}
	}
	for(auto fir:start)
	{
		cnt[fir]+=1;
		dfs(fir,arr[fir].size());
		cnt[fir]-=1;
	}
	cout<<final_ans;
	return 0;
}

[USACO05DEC] Scales S

题目描述

约翰有一架用来称牛的体重的天平。与之配套的是 $ N \ ( 1 \leq N \leq 1000 ) $ 个已知质量的砝码(所有砝码质量的数值都在 32 32 32 位带符号整数范围内)。

每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(约翰不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当约翰把砝码放到她的蹄子底下,她就会尝试把砝码踢到约翰脸上)。

天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于 $ C \ ( 1 \leq C \leq 2^{30} ) $ 时,天平就会被损坏。砝码按照它们质量的大小被排成一行。并且,这一行中从第 3 3 3 个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。

约翰想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少。由于天平的最大承重能力为 C C C,他不能把所有砝码都放到天平上。

现在约翰告诉你每个砝码的质量,以及天平能承受的最大质量,你的任务是选出一些砝码,使它们的质量和在不压坏天平的前提下是所有组合中最大的。

输入格式

第 1 1 1 行输入两个用空格隔开的正整数 $ N $ 和 $ C $。

第 2 2 2 到 $ N+1 $ 行:每一行仅包含一个正整数,即某个砝码的质量。保证这些砝码的质量是一个不下降序列。

输出格式

输出一个正整数,表示用所给的砝码能称出的不压坏天平的最大质量。

样例 #1

样例输入 #1

3 15
1
10
20

样例输出 #1

11

代码实现

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX_N 1000
int fama[MAX_N+5];
int final_ans=0;	
int n,c;
bool cmp(int a,int b)
{
	return a>b;
}
void dfs(int i,int ans)
{
	if(i==n)
	{
		final_ans=max(final_ans,ans);
		return ;
	}
	if(ans+fama[i+1]<=c)dfs(i+1,ans+fama[i+1]);
	if(ans+fama[i+1]+fama[i+2]>c)
	dfs(i+1,ans);
	return ;
}
int main()
{
	cin>>n>>c;
	for(int i=1;i<=n;i++)cin>>fama[i];
	sort(fama+1,fama+1+n,cmp);
	dfs(0,0);
	cout<<final_ans;
	return 0;
 } 

【XR-2】奇迹

题目背景

相信奇迹的人,本身就和奇迹一样了不起。——笛亚 《星游记》

题目描述

我们称一个日期为一个八位数,第 1~4 位构成年,第 5~6 位构成月,第 7~8 位构成日,不足位数用 0 补足。同时,要求日期所代表的这一天真实存在,且年的范围为 1~9999。

出现奇迹的日期都存在相同的特点:由“日”组成的两位数,由“月+日”组成的四位数,由“年+月+日”组成的八位数均为质数。但并不是所有存在这样特点的日期都一定会出现奇迹。

现在,你得到了一个可能会出现奇迹的日期,然而不幸的是这个日期却是残缺的,八位中可能有若干位无法确定。你需要知道这个日期有多少种可能,这样你才能做好充足的准备去迎接奇迹的到来。

输入格式

本题有多组数据。

第一行一个正整数 T T T,表示数据组数。

接下来的 T T T 行,每行一个八位字符串。其中第 i i i 位如果为 -,则表示日期的第 i i i 位无法确定,否则表示日期的第 i i i 位为字符串中第 i i i 位上的数字。

输出格式

对每组数据,一行一个整数,表示答案。

样例 #1

样例输入 #1

2
53-7-3-7
20190629

样例输出 #1

6
0

提示

【样例 1 1 1 说明】

53-7-3-7 的 6 6 6 种可能的日期如下:

53070307
53070317
53170307
53370307
53570317
53770307

【数据规模与约定】

一共 10 10 10 个测试点,记 c c c 为八位字符串中 - 的个数。

对前 9 9 9 个测试点,在第 i i i 个测试点中保证 c = i − 1 c = i - 1 c=i−1。

对 100 % 100\% 100% 的数据保证 1 ≤ T ≤ 10 1 \le T \le 10 1≤T≤10。

代码实现

#include<iostream>
#include<math.h>
using namespace std;
#define MAXSIZE 10000005
int prim[10005],zhishu[10005],vis[10005],runnian[10005];
int m_to_d[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int ans=0;
int cnt=0;
int s[9];
void Init()
{

	for(int i=2;i<=10005;i++)
	{
		if(!vis[i])
		{
			prim[++cnt]=i;
			zhishu[i]=1;
			vis[i]=1;
		}
		for(int j=1;j<=cnt;j++)
		{
			if(i*prim[j]>10005)break;
			vis[prim[j]*i]=1;
			if(i%prim[j]==0)break;
		}
	}
	for(int i=1;i<=9999;i++)
	{
		if(i%4==0)
		if(i%100!=0)runnian[i]=1;
		else if(i%400==0)runnian[i]=1;
	}
	return ;
}
bool pdzs(int x)
{
	if(x < 2) return 0;
	for(int i= 1; i <= cnt; i++)
	if(x % prim[i] == 0) return x == prim[i];
	return 1;
}
void dfs(int pos,int num,int rn,int dy)
{
	if(pos==0)
	{
		if(num<=1231)return ;
		if(rn==1&&!runnian[num/10000])return ;
		if(pdzs(num))ans++;
		return ;
	}
	if(pos==4)
	{
		if(num<31||num>1231)return ;
		if(dy==1&&m_to_d[num/100]!=31)return ;
		if(!pdzs(num))return ;
		if(num%100==29&&num/100==2)rn=1;
	}
	if(pos==6)
	{
		if(num==0||num>31)return ;
		if(!pdzs(num)) return ;
		if(num==31)dy=1;
	}
	if(s[pos]==-1)for(int i=0;i<=9;i++)dfs(pos-1,num+i*pow(10,8-pos),rn,dy); 
	else dfs(pos-1,num+s[pos]*pow(10,8-pos),rn,dy);
}
int main()
{
	int t;
	cin>>t;
	Init();
	while(t--)
	{
		ans=0;
		char c;
		for(int i=1;i<=8;i++)
		{
			cin>>c;
			s[i]=(c=='-'?-1:c-'0');
		}
		dfs(8,0,0,0);
		cout<<ans<<endl;
	}
	return 0;
 } 

油滴扩展

题目描述

在一个长方形框子里,最多有 N N N 个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这 N N N 个点上放置油滴,才能使放置完毕后所有油滴占据的总面积最大呢?(不同的油滴不会相互融合)

注:圆的面积公式 S = π r 2 S = \pi r^2 S=πr2,其中 r r r 为圆的半径。

输入格式

第一行,一个整数 N N N。

第二行,四个整数 x , y , x ′ , y ′ x, y, x', y' x,y,x′,y′,表示长方形边框一个顶点及其对角顶点的坐标。

接下来 N N N 行,第 i i i 行两个整数 x i , y i x_i, y_i xi​,yi​,表示盒子内第 i i i 个点的坐标。

输出格式

一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)。

样例 #1

样例输入 #1

2
20 0 10 10
13 3
17 7

样例输出 #1

50

提示

代码实现

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 6 1 \le N \le 6 1≤N≤6,坐标范围在 [ − 1000 , 1000 ] [-1000, 1000] [−1000,1000] 内。

#include<iostream>
#include<math.h>
using namespace std;
#define PI 3.1415926535
double x[10],y[10],r[10];
double xa,xb,ya,yb;
double s;
double yd=0;
int vis[10],w[10];
int n;
double dis(int a,int b)
{
	return sqrt(pow(x[a]-x[b],2)+pow(y[a]-y[b],2));
}
void dfs(int id,double num)
{
	if(id==n+1)
	{	
		yd=max(yd,num);
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(vis[i])continue;
		vis[i]=1;
		w[id]=i;
		r[id]=1000000;
		r[id]=min(r[id],fabs(xa-x[i]));
		r[id]=min(r[id],fabs(xb-x[i]));
		r[id]=min(r[id],fabs(ya-y[i]));
		r[id]=min(r[id],fabs(yb-y[i]));
		for(int j=1;j<id;j++)
		{
			double dd=dis(w[id],w[j]);
			if(dd<=r[j])
			{
				r[id]=0;
				break;
			}
			r[id]=min(r[id],dd-r[j]);
		}
		dfs(id+1,num+PI*r[id]*r[id]);
		vis[i]=0;
	}
	return ;
}
int main()
{
	cin>>n;
	cin>>xa>>ya>>xb>>yb;
	s=fabs(xa-xb)*fabs(ya-yb);
	for(int i=1;i<=n;i++)r[i]=1000000;
	for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
	dfs(1,0);
	s-=yd;
	printf("%.0lf",s);//自带四舍五入 
	return 0;
} 

标签:优先,int,ans,样例,vis,Part,砝码,3.1,id
From: https://blog.csdn.net/m0_70897036/article/details/139363833

相关文章

  • [AIGC] 广度优先搜索(Breadth-First Search,BFS)详解
    广度优先搜索(Breadth-FirstSearch,简称BFS)是一种用于图或者树的搜索算法,它的特点是按照“广度”进行搜索,即在扩展搜索路线的时候,BFS会先考虑当前节点的所有邻近节点,也就是说,它逐层地进行搜索。文章目录基本原理实现方法应用场景总结基本原理广度优先搜索的基本......
  • 华为od机考_精准核酸检测_Java(深度优先搜索)
    华为od机考_精准核酸检测_Java题目为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准還定可能被感染的人群。现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是否存在轨迹的交叉。现在给定一组确诊人员编号(X1,X2,X3,…Xn),在所有人当中......
  • 3.1 编辑器和集成开发环境
    3.1.1编辑器、集成开发环境与其它工具因为Go语言还是一门相对年轻的编程语言,所以不管是在集成开发环境(IDE)还是相关的插件方面,发展都不是很成熟。不过目前还是有一些IDE能够较好地支持Go的开发,有些开发工具甚至是跨平台的,你可以在Linux、MacOSX或者Windows下工作。......
  • 60天【代码随想录算法训练营34期】第十章 单调栈part03 (84.柱状图中最大的矩形)
    84.柱状图中最大的矩形classSolution:deflargestRectangleArea(self,heights:List[int])->int:s=[0]result=0heights.insert(0,0)heights.append(0)foriinrange(1,len(height......
  • 【Unity2D 2022:Particle System】添加粒子特效
    一、创建粒子系统游戏物体1. 创建粒子系统游戏物体SmogEffect 2.给粒子特效添加精灵贴图    (1)启用TextureSheetAnimation(纹理表动画)    (2)点击加号添加一个纹理,并将两张厌恶图片导入到纹理中3.设置两张图片随机播放(防止烟雾粒子变化)   ......
  • 文件上传时各配置目录优先级详解
    Tomcat配置目录有以下两个1.spring.servlet.multipart.location:文件上传路径2.server.tomcat.basedir:配置Tomcat运行日志和临时文件的目录。如果生产中配置了这两个目录,当上传文件时,他们的优先级是?    当上传文件时,代码执行到Request类,在发现使用时spring.servlet.mult......
  • Failed to resolve org.junit.jupiter:junit-jupiter-engine:5.3.1
    跟着尚硅谷学SSM测试这块老不对就没按视频里的用的junit4平替了今天的@BeforeEach平替不了搜了半天找不到解决方法就把报错的都整到依赖里了然后就好了也不知道具体咋回事<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit......
  • GEE 27 高级栅格可视化 Advanced Raster Visualization(Part6)
    Overview ThischaptershouldhelpusersofEarthEnginetobetterunderstandrasterdatabyapplyingvisualizationalgorithmssuchashillshading,hillshadows,andcustomcolormaps.Wewillalsolearnhowimagecollectiondatasetscanbeexploredbyani......
  • 【WEEK14】 【DAY2】Shiro Part 7【English Version】
    2024.5.28TuesdayContinuationfromprevious【WEEK14】【DAY1】ShiroPart6【EnglishVersion】Contents15.8.IntegrateShirowithThymeleaf15.8.1.Modifypom.xmltoAddDependencies15.8.1.1.Importingtheshiro-thymeleafIntegrationPackage15.8.1.2.......
  • Particles.js:为Web项目增添动态粒子效果
    Particles.js:为Web项目增添动态粒子效果示例介绍Particles.js是一个轻量级的JavaScript库,用于在Web页面上创建和管理动态粒子效果。它允许开发者通过简单的配置文件实现复杂的动画效果,为网页增添视觉吸引力。粒子可以是点、线、图像等,能够根据用户交互进行动态变化,Particles.......