PAT 天梯赛 L3 题目整理

目录

 

L3-001 凑零钱 (30 分)(回溯+剪枝)

L3-002 特殊堆栈 (30 分)(二分)

L3-003 社交集群 (30 分)(并查集)

L3-004 肿瘤诊断 (30 分)(三维bfs)

L3-016 二叉搜索树的结构 (30 分)(数组+字符串+函数定义+不用定义树结构的)

L3-005 垃圾箱分布 (30 分)(dijkstra)

L3-013 非常弹的球 (30 分)(物理公式水题)


L3-001 凑零钱 (30 分)(回溯+剪枝)

【分析】

  1. dfs搜一下,因为排过序,所以数组递增排列,故第一组满足sum==w的序列一定是满足条件的序列,所以不用把所有的序列都搜出来的;
  2. 注意剪枝;一次符合之后f=1之后就不再进行递归直接return掉;如果所有的钱加起来都达不到要求,就不用搜了【这里会wa倒数第二个点和T最后一个点】;

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e4+10;
int a[maxn];
vector<int>dp,t;
int n,w,sum,f;

void dfs(int x)
{
	if(f)return;
	if(sum>w || x>=n)return;
	if(sum==w)
	{
		f=1;
		t.assign(dp.begin(),dp.end());
		return;
	}
	dp.push_back(a[x]);
	sum+=a[x];
	dfs(x+1);
	sum-=a[x];dp.pop_back();
	dfs(x+1);
}

int main()
{
	scanf("%d%d",&n,&w);
	int sum=0;
	for(int i=0;i<n;++i)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	sort(a,a+n);
	if(sum<w){puts("No Solution");return 0;}
	else if(sum==w)
	{
		for(int i=0;i<n;++i)
			(i==n-1)?printf("%d\n",a[i]):printf("%d ",a[i]);
		return 0;
	}
	f=0;dfs(0);
	if(!f)puts("No Solution");
	else
	for(int i=0;i<t.size();++i)
		(i==t.size()-1)?printf("%d\n",t[i]):printf("%d ",t[i]);
}

L3-002 特殊堆栈 (30 分)(二分)

【分析】如果不用二分直接数组或vector拷贝会超时;二分找到元素位置,再执行删除或插入操作

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+10;
int a[maxn];
vector<int>v;
vector<int>::iterator it;

int main()
{
	int n;scanf("%d",&n);
	int cnt=0;
	while(n--)
	{
		string s;cin>>s;
		if(s=="Push")
		{
			int x;scanf("%d",&x);
			a[cnt++]=x;
			it=lower_bound(v.begin(),v.end(),x);
			v.insert(it,x);
		}
		else if(s=="Pop")
		{
			if(cnt>0)
			{
				it=lower_bound(v.begin(),v.end(),a[cnt-1]);
				v.erase(it);
				printf("%d\n",a[--cnt]);
			}
			else puts("Invalid");
		}
		else if(s=="PeekMedian")
		{
			if(cnt==0)puts("Invalid");
			else
			{
				int x=v.size();
				if(x&1)printf("%d\n",v[x/2]);
				else printf("%d\n",v[x/2-1]);
			}
		}
	}
}

L3-003 社交集群 (30 分)(并查集)

【分析】并查集,注意map是按键值排序的,如果用it->second的话并不是有序输出的;所以存数组里排个序好啦

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int pre[maxn];
vector<int>v[maxn];
int mp[maxn];

int n;

bool cmp(int x,int y){return x>y;}
int finds(int x){return pre[x]==x?x:pre[x]=finds(pre[x]);}
void join(int x,int y)
{
	int fx=finds(x),fy=finds(y);
	if(fx!=fy)
		pre[fx]=fy;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)pre[i]=i;
	int maxx=-1;
	for(int i=1;i<=n;++i)
	{
		int k;scanf("%d: ",&k);
		for(int j=0;j<k;++j)
		{
			int x;scanf("%d",&x);
			v[x].push_back(i);
			maxx=max(maxx,x);
		}
	}
	for(int i=1;i<=maxx;++i)
	{
		int x;
		if(v[i].size())x=v[i][0];
		for(int j=1;j<v[i].size();++j)
			join(x,v[i][j]);
	}
	int cnt=0;
	for(int i=1;i<=n;++i)
	{
		int fx=finds(i);
		if(!mp[fx])cnt++;
		mp[fx]++;
	}
	printf("%d\n",cnt);
	sort(mp,mp+maxn,cmp);
	for(int i=0;i<cnt;++i)
		(i==cnt-1)?printf("%d\n",mp[i]):printf("%d ",mp[i]);
}

L3-004 肿瘤诊断 (30 分)(三维bfs)

【分析】注意这个肿瘤块是立体的!上下左右前后共六个方位。我一开始用的是二维的8个方位总是2个测试点答案错误....太蠢了太蠢了

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1300;
int mp[70][maxn][140];
int vis[70][maxn][140];
int dir[6][3]={{0,0,1},{0,0,-1},{0,-1,0},{0,1,0},{-1,0,0},{1,0,0}};
int m,n,l,t,cnt;

struct node{
	int z,x,y;
};

void bfs(int z,int x,int y)
{
	if(mp[z][x][y]==1)cnt++;
	queue<node>q;
	q.push({z,x,y});
	vis[z][x][y]=1;
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		for(int i=0;i<6;++i)
		{
			z=t.z+dir[i][0];
			x=t.x+dir[i][1];
			y=t.y+dir[i][2];
			if(x<0 || x>=m || y<0 || y>=n || z<0 || z>l || vis[z][x][y] || mp[z][x][y]==0)continue;
			if(mp[z][x][y]==1)q.push({z,x,y});
			cnt++;vis[z][x][y]=1;
		}		
	}
}
int main()
{
	scanf("%d%d%d%d",&m,&n,&l,&t);
	int sum=0;
	for(int k=0;k<l;++k)
		for(int i=0;i<m;++i)
			for(int j=0;j<n;++j)
				scanf("%d",&mp[k][i][j]);
	memset(vis,0,sizeof(vis));
	for(int k=0;k<l;++k)
		for(int i=0;i<m;++i)
		{
			for(int j=0;j<n;++j)
			{
				if(mp[k][i][j] && !vis[k][i][j])bfs(k,i,j);
				if(cnt>=t)sum+=cnt;
				cnt=0;
			}
		}
	printf("%d\n",sum);
}

L3-016 二叉搜索树的结构 (30 分)(数组+字符串+函数定义+不用定义树结构的)

【分析】

不用定义结构体,直接用数组来做;l[i] & r[i]分别代表节点i的左右节点的下标;

deep数组存每个节点对应的index的深度;

mp存每个值的对应的下标

因为上面的数组的值对应的都是下标,所以要用map存一下;

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=110;
int a[maxn],l[maxn],r[maxn];
int pre[maxn],deep[maxn];
map<int,int>mp;
int n,q;
int root;

void insert(int &Root,int fa,int dep,int id)
{
//	cout<<l[Root]<<","<<r[Root]<<endl;
	if(Root==-1)
	{
		Root=id;//这里就是给l,r数组赋值;如果是-1那么会走这个if语句,然后赋值返回 
		pre[id]=fa;
		deep[id]=dep;
		return;
	}
	if(a[id]<a[Root])insert(l[Root],Root,dep+1,id);
	else insert(r[Root],Root,dep+1,id);
}
int main()
{
	scanf("%d",&n);
	memset(l,-1,sizeof(l));
	memset(r,-1,sizeof(r));
	root=-1;
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&a[i]);
		insert(root,-1,1,i);
		mp[a[i]]=i;
	}
	scanf("%d",&q);getchar();
	while(q--)
	{
		string s;getline(cin,s);
		int x,y,f=0;
		if(s.find("root")!=string::npos)
		{
			sscanf(s.c_str(),"%d is the root",&x);
			if(mp.find(x)!=mp.end() && a[root]==x)f=1;
		}
		else if(s.find("siblings")!=string::npos)
		{
			sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
			if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==pre[mp[y]])f=1;	
		}
		else if(s.find("parent")!=string::npos)
		{
			sscanf(s.c_str(),"%d is the parent of %d",&x,&y);	
			if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[y]]==mp[x])f=1;
		}
		else if(s.find("left")!=string::npos)
		{
			sscanf(s.c_str(),"%d is the left child of %d",&x,&y);	
			if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==mp[y] && x<y)f=1;
		}
		else if(s.find("right")!=string::npos)
		{
			sscanf(s.c_str(),"%d is the right child of %d",&x,&y);	
			if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==mp[y] && x>y)f=1;
		}else if(s.find("same")!=string::npos)
		{
			sscanf(s.c_str(),"%d and %d are on the same level",&x,&y);	
			if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && deep[mp[x]]==deep[mp[y]])f=1;
		}
		if(f)puts("Yes");
		else puts("No");
	}
}

L3-005 垃圾箱分布 (30 分)(dijkstra)

【分析】和pat甲级一道题类似;把垃圾箱的下标转换成n之后的数,然后求出单源最短路径即可;

排序的话,是按照最短路径->最小平均值->最小下标

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+20;
const int inf=0x3f3f3f3f;
int e[maxn][maxn];
int vis[maxn],dis[maxn];
int n,m,k,d;

void dijkstra(int x)
{
	memset(dis,inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[x]=0;
	for(int i=1;i<=m+n;++i)
	{
		int now=-1,minn=inf;
		for(int j=1;j<=m+n;++j)
			if(!vis[j] && dis[j]<minn)
				minn=dis[j],now=j;
		if(now==-1)break;
		vis[now]=1;
		for(int j=1;j<=m+n;++j)
			if(!vis[j] && dis[now]+e[now][j]<dis[j])
				dis[j]=e[now][j]+dis[now];
	}
}
int main()
{
	memset(e,inf,sizeof(e));
	scanf("%d%d%d%d",&n,&m,&k,&d);
	while(k--)
	{
		string s1,s2;cin>>s1>>s2;
		int dist;scanf("%d",&dist);
		if(dist>d)continue;
		int x,y;
		if(s1[0]=='G')x=stoi(s1.substr(1))+n;
		else x=stoi(s1);
		if(s2[0]=='G')y=stoi(s2.substr(1))+n;
		else y=stoi(s2);
		e[x][y]=e[y][x]=dist;
	}
	int maxx=0,sum=0,f=0,id;
	for(int i=n+1;i<=n+m;++i)
	{
		dijkstra(i);
		f=0;
		int mind=inf,sum1=0;
		for(int j=1;j<=n;++j)
		{
			if(dis[j]>d){sum1=-1;break;}
			sum1+=dis[j];
			mind=min(mind,dis[j]);
		}
		if(sum1!=-1)
		{
			f=1;
			if(mind>minn)maxx=mind,id=i,sum=sum1;
			else if(mind==maxx && sum1<sum)sum=sum1,id=i;
		}
	}
	if(!f)puts("No Solution");
	else
		printf("G%d\n%.1lf %.1lf\n",id-n,maxx*1.0,sum*1.0/n);
	return 0;
}

L3-013 非常弹的球 (30 分)(物理公式水题)

【分析】其实刚看到这题我是拒绝的...因为是物理题

不过再看  发现其实是很基础的物理题啦,而且公式都给出来了,再推下就好了

【代码】

#include<bits/stdc++.h>
using namespace std;

const double esp=0.0001;

int main()
{
	double g=9.8;
	double e=1000;
	double res=0;

	double w,p;scanf("%lf%lf",&w,&p);
	w/=100;
	p=(100-p)/100;
	double v=1;
	while(v>esp)
        {
    	    v=sqrt(2*e/w);   
            double vy=v*sqrt(2)/2;
            double t=vy/g;
    	    res+=vy*t*2;
    	    e*=p;
        }
        printf("%.3lf\n", res);
        return 0;
}

 

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值