pat练习(1128,1129,1130,1131)

总结:

(1)图论的dfs还有些不熟练,需要加强练习。

(2)多学学STL。

 

pat-1128(思维)

思路:

已知一个点,将它的向下和对角线的元素标记好就行了,然判断接下来的点是否标记过了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1005;
int mp[maxn][maxn];
int main(void)
{
	int n,k,i,x,fg,j;
	scanf("%d",&k);
	while(k--){
		scanf("%d",&n);fg=0;
		memset(mp,0,sizeof(mp));
		for(i=1;i<=n;i++){
			scanf("%d",&x);
			if(fg==0&&mp[i][x]==0)
			for(j=i;j<=n;j++){
				mp[j][x]=1;
				if(x+(j-i)<=n) mp[j][x+j-i]=1;
				if(x-(j-i)>=1) mp[j][x-j+i]=1;
			}
			else fg=1;
		}
		if(fg==1) printf("NO\n");
		else printf("YES\n");
	}
	return 0;
} 

 

pat-1129(排序)

思路:这次的排序是输出前k个或小于k个“最大的值”,一开始我想用优先队列去做,但是每次都要入队,出队,很耗时;

就超时了。

做法一:

将前k个或小于k个数字排序。(参考文章

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100100;
struct Node{
	int num,id;
	bool operator <(Node a) const{
		if(num!=a.num) return num>a.num;
		else return id<a.id;
	}
}cur[120];
int vis[maxn];
int main(void)
{
	Node tmp;
	int n,k,i,j,x,y,pos=0,fg;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++){
		scanf("%d",&x);
		tmp.id=x;tmp.num=++vis[x];
		if(i==1) cur[++pos]=tmp;
		else{
			printf("%d:",x);
			sort(cur+1,cur+1+pos);
			if(pos<k){
				fg=0;
				for(j=1;j<=pos;j++){
					printf(" %d",cur[j].id);
					if(cur[j].id==x) cur[j]=tmp,fg=1;
				}
				if(fg==0) cur[++pos]=tmp;
			}
			else{
				fg=0;
				for(j=1;j<=pos;j++){
					printf(" %d",cur[j].id);
					if(cur[j].id==x) cur[j]=tmp,fg=1;
				}
				if(fg==0&&(cur[pos].num<tmp.num||(cur[pos].num==tmp.num&&cur[pos].id>tmp.id))) cur[pos]=tmp;
			}
			printf("\n");
		}
	}
	return 0;
}

做法二:

用set做,因为set中所有元素都是唯一的,而且根据大小排序,就很方便。(参考文章

#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
const int maxn = 100100;
struct Node{
	int id,num;
	bool operator <(Node a) const{
		if(num!=a.num) return num>a.num;
		else return id<a.id;
	}
}cur[120];
int vis[maxn]={0};
int main(void)
{
	int n,k,i,j,x,y;
	set <Node> st;
	Node tmp; 
	scanf("%d%d",&n,&k);
	for(i=0;i<n;i++){
		scanf("%d",&x);
		tmp.id=x;tmp.num=vis[x];
		if(i){
			printf("%d:",x);
			j=0;
			for(auto it=st.begin();j<k&&it!=st.end();it++,j++) printf(" %d",it->id);
			printf("\n");
		}
		auto it=st.find(tmp);
		if(it!=st.end()) st.erase(it);
		vis[x]++;tmp.num=vis[x];
		st.insert(tmp);
	}
	return 0;
}

 

pat-1130(表达式树+括号)

思路:加括号的条件是左,右子树中有一个节点非空即可,但是最后要去掉两遍的括号即可。

(一开始没想到怎么找根节点,就找最长的str,从根节点遍历得到的str最长,后来想想,在输入的时候标记出现的儿子节点就行了,没被标记的节点一定是根节点)。

注意:如果节点只有一个要特殊判断一下。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 100100;
string ss[maxn];
struct Node{
	int id,le,ri;
}cur[maxn];
int n,vis[maxn];
string str;
void inorder(int x)
{
	if(x!=-1){
		if(cur[x].le!=-1||cur[x].ri!=-1) str+='(';
		inorder(cur[x].le);
		str+=ss[x];
		inorder(cur[x].ri);
		if(cur[x].le!=-1||cur[x].ri!=-1) str+=')';
	}
}
int main(void)
{
	int i,j,x,y,len;
	string op;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		cin>>op;
		scanf("%d%d",&x,&y);
		ss[i]=op;
		cur[i].id=i;cur[i].le=x;cur[i].ri=y;
	}
	string tsp="";
	if(n==1){
		cout<<ss[1]<<endl;
		return 0;
	}
	for(i=1;i<=n;i++){
		str="";
		inorder(i);
		if(str.length()>tsp.length()) tsp=str;
	}
	for(i=1,len=tsp.length();i<len-1;i++) printf("%c",tsp[i]);
	return 0;
}

 

pat-1131(深搜)

思路:这道题一开始用bfs,然后要判断的结果太多了就卡住了。

参考了柳神的文章,可以再深搜时记录要求的信息(经过的节点,转弯的次数,并且记录路径),

转弯路径没法直接dfs找出,就从已知的路径中找转弯的次数就好了,记录节点的边可以用line(x*n+y)这种方式记录,

也可以用二维数组记录,注意,路径要提前记录st节点。

反思:

(1)所求数据过多时,可以通过一次dfs同时更新不同数据,并且利用已有数据求出未知数据。

(2)二位数组可以开到10000*10000,vector数据可以pop_back()。

(3)深搜完要回溯,返还数据。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
using namespace std;
const int maxn = 100100;
const int INF = 99999999;
int vis[maxn],dis[maxn],st,ed,micnt,mitran;
vector <int> vc[10001],path,tmpath;
map <int,int> line;
int tran(vector <int> vv)
{
	int i,v,pre=0,cnt=0;
	for(i=1;i<vv.size();i++){
		if(pre!=0&&line[vv[i-1]*10000+vv[i]]!=pre) cnt++;
		pre=line[vv[i-1]*10000+vv[i]];
	}
	return cnt;
}
void dfs(int u,int cnt)
{
	if(u==ed&&(cnt<micnt||(cnt==micnt&&tran(tmpath)<mitran))){
		path=tmpath;
		micnt=cnt;
		mitran=tran(tmpath);
	}
	if(u==ed) return ;
	for(int i=0;i<vc[u].size();i++){
		int v=vc[u][i];
		if(!vis[v]){
			vis[v]=1;
			tmpath.push_back(v);
			dfs(v,cnt+1);
			vis[v]=0;
			tmpath.pop_back();
		}
	}
}
int main(void)
{
	int n,m,k,i,j,x,y;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&m);
		for(j=1;j<=m;j++){
			scanf("%d",&x);
			if(j==1) y=x;
			else{
				vc[x].push_back(y);
				vc[y].push_back(x);
				line[x*10000+y]=line[y*10000+x]=i;
				y=x;
			}
		}
	}
	scanf("%d",&k);
	while(k--){
		scanf("%d%d",&st,&ed);
		mitran=INF;micnt=INF;
		memset(vis,0,sizeof(vis));
		tmpath.clear();
		tmpath.push_back(st);
		vis[st]=1;
		dfs(st,0);
		x=0;y=st;
		printf("%d\n",micnt);
		for(i=1;i<path.size();i++){
			if(line[path[i-1]*10000+path[i]]!=x){
				if(x!=0) printf("Take Line#%d from %04d to %04d.\n",x,y,path[i-1]);
				x=line[path[i-1]*10000+path[i]];
				y=path[i-1];
			}
		}
		printf("Take Line#%d from %04d to %04d.\n",x,y,ed);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MOOC PAT练习是指在在线课程平台上进行的编程能力考试。它提供了一系列编程题目,旨在帮助学生提高解决问题的能力和编程技能。下面是对此练习的回答: MOOC PAT练习是一种非常有益的学习资源。它可以帮助学生在虚拟的环境中解决实际问题,并通过编程来提高解决问题的能力。通过这种方式,学生可以更好地理解和掌握编程语言和算法知识。 MOOC PAT练习不仅可以提升学生的编程能力,还可以培养学生的创新思维和团队合作精神。在解决编程题目时,学生需要思考合适的算法和数据结构,同时还需要灵活运用编程语言来实现自己的想法。这样的练习可以锻炼学生的分析问题和解决问题的能力,培养其创新和合作意识。 通过MOOC PAT练习,学生可以接触到各种各样的编程题目,涵盖了不同的难度级别和主题领域。这对于学生来说是一个很好的学习机会,可以不断地挑战自己、提高自己。此外,该练习还提供了评测功能,学生可以实时了解自己的答题情况,并获得相应的反馈和建议,这有助于他们更好地调整学习进度和方向。 总结来说,MOOC PAT练习是一个非常有价值的学习资源,它可以提升学生的编程能力、培养创新和合作意识,并且通过不断挑战和实践来提高自己。对于想要学习编程的人来说,参加MOOC PAT练习是一个不错的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值