PAT 天梯赛 L2 部分题目整理

目录

L2-002 链表去重 (25 分)

L2-003 月饼 (25 分)(排序+贪心+细节注意)

L2-005 集合相似度 (25 分)(set的应用)

L2-007 家庭房产 (25 分)(并查集+STL的应用)

L2-008 最长对称子串 (25 分)(字符串处理)

L2-010 排座位 (25 分)(并查集)

L2-012 关于堆的判断 (25 分)(最小堆的建立+自下而上)

L2-018 多项式A除以B (25 分)(多项式除法)

L2-020 功夫传人 (25 分)(递归求解)

L2-022 重排链表 (25 分)(结构体运用+有一个小坑)

L2-028 秀恩爱分得快 (25 分)(模拟+两种方法)


L2-002 链表去重 (25 分)

【分析】结构体数组,下标存该结点地址;2个vector,分别存已访问过的和未访问过的键值;输出的时候nxt输的是下一个元素的adr

 和甲级的这道题一样    1097 Deduplication on a Linked List (25 分)(链表模拟)

【代码】

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

const int maxn=1e6+10;
struct node{
	int adr;
	int val;
	int nxt;
}a[maxn];
int vis[maxn];

int main()
{
	int adr,n;scanf("%d%d",&adr,&n);
	for(int i=0;i<n;++i)
	{
		int adr,val,nxt;
		scanf("%d%d%d",&adr,&val,&nxt);
		a[adr].val=val;a[adr].nxt=nxt;a[adr].adr=adr;
	}
	memset(vis,0,sizeof(vis));
	vector<node>v1,v2;
	for(int i=adr;;i=a[i].nxt)
	{
		if(i==-1)break;
//		cout<<"i="<<i<<","<<a[i].val<<"--\n";
		if(!vis[abs(a[i].val)])v1.push_back(a[i]);
		else v2.push_back(a[i]);
		vis[abs(a[i].val)]=1;
	}
	int l1=v1.size(),l2=v2.size();
	for(int i=0;i<l1;++i)
		(i==l1-1)?printf("%05d %d -1\n",v1[i].adr,v1[i].val):printf("%05d %d %05d\n",v1[i].adr,v1[i].val,v1[i+1].adr);
	for(int i=0;i<l2;++i)
		(i==l2-1)?printf("%05d %d -1\n",v2[i].adr,v2[i].val):printf("%05d %d %05d\n",v2[i].adr,v2[i].val,v2[i+1].adr);
	
}

L2-003 月饼 (25 分)(排序+贪心+细节注意)

【题意】求最大收益

【分析】把收益与库存的比值+下标存入然后排序;注意库存量和售价不是整型,题上只说了是正数,但没有说是整数。所以!!如果没有注意到这一点,测试点2是过不了的.... 就会只有23分了

【代码】

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

const int maxn=1e3+10;
double a[maxn],b[maxn];
vector<pair<double,int> >v;

bool cmp(pair<double,int>a,pair<double,int>b)
{
	return a.first<b.first;
} 

int main()
{
	int n,d;scanf("%d%d",&n,&d);
	for(int i=0;i<n;++i)scanf("%lf",&a[i]);
	for(int i=0;i<n;++i)scanf("%lf",&b[i]);
	for(int i=0;i<n;++i)v.push_back(make_pair(1.0*b[i]/a[i],i));
	sort(v.begin(),v.end(),cmp);
//	for(int i=0;i<v.size();++i)cout<<v[i].first<<","<<v[i].second<<endl;
	double sum=0;
	int f=1;
	for(int i=v.size()-1;i>=0;--i)
	{
		if(d<=0)break;
		int id=v[i].second;
		if(a[id]<=d)sum+=b[id],d-=a[id];
		else sum+=v[i].first*d,d=0;
	}
	printf("%.2lf\n",sum);//如果需求大于全部加起来的库存,是要输出的 
}

L2-005 集合相似度 (25 分)(set的应用)

【题意】求两个集合的都有的不相同的整数个数和一共有的的比值

【分析】二维的set存一下;(类似于vector<int>v[maxn],之前没用过,没想到可以用耶xixi开心)

【代码】

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

const int maxn=60;
set<int>s[maxn];
int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		int t;scanf("%d",&t);
		while(t--)
		{
			int x;scanf("%d",&x);
			s[i].insert(x);
		}
	}
	int k;scanf("%d",&k);
	while(k--)
	{
		int a,b;scanf("%d%d",&a,&b);
		int l1=s[a].size(),l2=s[b].size();
		set<int>::iterator it;
		int sum=0;
		for(it=s[a].begin();it!=s[a].end();++it)
			if(s[b].count(*(it)))sum++;
		int x=l1+l2-sum;
		printf("%.2lf%\n",sum*1.0/x*100);
		
	}
}

L2-007 家庭房产 (25 分)(并查集+STL的应用)

【分析】与  1114 Family Property (25 分)(并查集) 同;这次写得有点麻烦了,但是一遍就过还是很开心嘛~

【代码】

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

const int maxn=1e5+10;
struct node{
	int id,people=0;
	double avg_num=0;
	double avg_areas=0;
}a[maxn];
bool cmp(node x,node y){return x.avg_areas!=y.avg_areas?x.avg_areas>y.avg_areas:x.id<y.id;}

int pre[maxn],vis[maxn];
set<int>s;
vector<node>v;
int n;

int finds(int x){return pre[x]==x?x:pre[x]=finds(pre[x]);}
void join(int x,int y)
{
	int fx=finds(x);
	int fy=finds(y);
	if(fx<fy)pre[fy]=fx;
	else pre[fx]=fy;
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<maxn;++i)pre[i]=i;
	memset(vis,0,sizeof(vis));
	for(int i=0;i<n;++i)
	{
		int id,fa,ma,k;
		scanf("%d%d%d%d",&id,&fa,&ma,&k);	
		vis[id]=1;
		if(fa!=-1)vis[fa]=1,join(id,fa);
		if(ma!=-1)vis[ma]=1,join(id,ma);
		for(int i=0;i<k;++i)
		{
			int x;scanf("%d",&x);
			join(id,x);
			vis[x]=1;
		}
		double sets,areas;
		scanf("%lf%lf",&sets,&areas);
	
		a[id].avg_num=sets;
		a[id].avg_areas=areas;
	}	
	int f=0;
	for(int i=0;i<maxn;++i)
	{
		if(vis[i])
		{
			int f=finds(i);
			a[f].people++;	
			s.insert(f);
			if(f==i)continue;
			a[f].avg_num+=a[i].avg_num;
			a[f].avg_areas+=a[i].avg_areas;
		//	cout<<"f="<<f<<endl;
		}
	}
	int l=s.size();printf("%d\n",l);
	set<int>::iterator it;
	for(it=s.begin();it!=s.end();++it)
	{	
		int x=*it;
		node n;n.id=x;
		n.avg_num=1.0*a[x].avg_num/a[x].people;
		n.avg_areas=1.0*a[x].avg_areas/a[x].people;
		n.people=a[x].people;
		v.push_back(n);
	}
	sort(v.begin(),v.end(),cmp);
	for(int i=0;i<l;++i)
	{
		int y=v[i].people;
		printf("%04d %d %.3lf %.3lf\n",v[i].id,y,v[i].avg_num,v[i].avg_areas);
	}
	
}

L2-008 最长对称子串 (25 分)(字符串处理)

【分析】遍历i,比较s[i-j]和s[i+j],不断维护最大值;注意奇偶数的不同

【代码】

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

int main()
{
	string s;getline(cin,s);
	int len=s.length();
	int maxx=0;
	for(int i=0;i<len;++i)
	{
		for(int j=0;j<=i && i+j<len;++j)
		{
			if(s[i-j]==s[i+j+1])//cout<<i<<","<<j<<endl,
				maxx=max(j+j+2,maxx);
			else break;
		}
	}
	for(int i=0;i<len;++i)
	{
		for(int j=0;j<=i && i+j<len;++j)
		{
			if(s[i-j]==s[i+j])//cout<<i<<","<<j<<endl,
				maxx=max(j+j+1,maxx);
			else break;
		}
	}
	printf("%d\n",maxx);
}

L2-010 排座位 (25 分)(并查集)

【题意】分座位,有敌对关系的人不能坐在一起;朋友的朋友是朋友,敌人没有这个关系;

【分析】

  1. 因为朋友的朋友是朋友,但是敌对关系不满足。所以,把有直接朋友关系的人join一起
  2. 查询时,判断两点是否处于同一个连通块,然后根据例子画图,推算每种情况对应的两点之间的关系
  3. 然后~  就好啦!

【代码】

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

const int maxn=110;
int e[maxn][maxn];
int pre[maxn];
int n,m,k;

int finds(int x){return x==pre[x]?x:pre[x]=finds(pre[x]);}
void join(int x,int y)
{  
	int fx=finds(x);
	int fy=finds(y);
	if(fx!=fy)
		pre[fx]=fy;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	memset(e,0,sizeof(e));
	for(int i=0;i<=n;++i)pre[i]=i;
	for(int i=0;i<m;++i)
	{
		int a1,a2,r;
		scanf("%d%d%d",&a1,&a2,&r);
		if(r==1)join(a1,a2);
		e[a1][a2]=e[a2][a1]=r;
	}
	while(k--)
	{
		int x,y;scanf("%d%d",&x,&y);
		int fx=finds(x),fy=finds(y);
		int f;
		if(fx!=fy)
		{
			if(e[x][y]==0)f=1;
			else if(e[x][y]==-1)f=3;
		}
		else
		{
			if(e[x][y]==-1)f=2;
			else f=0;
		}
		if(f==0)puts("No problem");
		else if(f==1)puts("OK");
		else if(f==2)puts("OK but...");
		else if(f==3)puts("No way");
	}
 } 

L2-012 关于堆的判断 (25 分)(最小堆的建立+自下而上)

【分析】

由给定的序列建最小堆,但是题上说的是顺序插入一个初始为空的小顶堆

所以,是边读入数据边建立堆更新堆;建堆有两种方式,并且建立出的堆是不同的...

然后就是根据输入的字符串进行相关的判断;

这里,sscanf()是c语言中的函数,这里使用的时候要转换成char*【s.c_str()】

在判断是否是兄弟结点的时候(注意这里的兄弟结点是具有同一个父节点,而不是深度相同!!!只要判断在数组中的index即可【因为是从0开始的,所以要(index-1)/2】)

【代码】

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

const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int a[maxn];
int n,m,cnt;

void MinHeap(int i)
{
	if(i==0)return;
	while(i>0)
	{
		if(a[i]<a[(i-1)/2])
		{
			swap(a[i],a[(i-1)/2]);
			i=(i-1)/2;
		}
		else break;
	}
} 
int finds(int x)
{
	for(int i=0;i<n;++i)
		if(a[i]==x)return i;
	return -1;
}
int main()
{
	scanf("%d%d",&n,&m);
	cnt=0;
	memset(a,inf,sizeof(a));
	for(int i=0;i<n;++i)
	{
		scanf("%d",&a[i]);
		MinHeap(i);
	}
	getchar();
	while(m--)
	{
		string s;getline(cin,s);
		if(s.find("root")!=string::npos)
		{
			int x;sscanf(s.c_str(),"%d is the root",&x);//sscanf是c的函数,不可以直接用string,string是个类,要转换成char* 
			if(a[0]==x)puts("T");
			else puts("F"); 
		}
		if(s.find("siblings")!=string::npos)
		{
			int x,y;sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
			int id1=finds(x),id2=finds(y);
			if(id1>id2)swap(id1,id2);
			if((id1-1)/2==(id2-1)/2)puts("T");
			else puts("F");
		}
		if(s.find("parent")!=string::npos)
		{
			int x,y;sscanf(s.c_str(),"%d is the parent of %d",&x,&y);
			int id=finds(x);
			if(a[id*2+1]==y || a[id*2+2]==y)puts("T");
			else puts("F");
		}
		if(s.find("child")!=string::npos)
		{
			int x,y;sscanf(s.c_str(),"%d is a child of %d",&x,&y);
			int id=finds(y);
			if(a[id*2+1]==x || a[id*2+2]==x)puts("T");
			else puts("F");
		}
	}
}

L2-020 功夫传人 (25 分)(递归求解)

【分析】得道者的倍数用一个数组存起来,普通弟子用二维vector存起来;然后如果某个x的size为0,则为得道者,进行sum的求和;否则,继续递归下去找得道者即可;

【代码】

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

const int maxn=1e5+10;
int a[maxn];
vector<int>v[maxn];
int n;
double z,r;

double dfs(int x,int t)
{
	double sum=0;
	if(!v[x].size())sum+=a[x]*z*pow((1-0.01*r),t);
	else
	{
		for(int i=0;i<v[x].size();++i)
			sum+=dfs(v[x][i],t+1);
	}
	return sum;
}

int main()
{
	scanf("%d%lf%lf",&n,&z,&r);
	for(int i=0;i<n;++i)
	{
		int k;scanf("%d",&k);
		if(k==0)scanf("%d",&a[i]);
		else{
			while(k--)
			{
				int x;scanf("%d",&x);
				v[i].push_back(x);
			}
		}
	}
	double sum=dfs(0,0);
	printf("%d\n",(int)sum);
}

L2-022 重排链表 (25 分)(结构体运用+有一个小坑)

【分析】注意是有结点不在链表上的.....

【代码】

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

const int maxn=1e6+10;
struct node{
	int adr;
	int val;
	int nxt;
}a[maxn];
vector<int>v;
int main()
{
	int adr,n;scanf("%d%d",&adr,&n);
	for(int i=0;i<n;++i)
	{
		int adr,key,nxt;
		scanf("%d%d%d",&adr,&key,&nxt);
		a[adr].adr=adr;a[adr].nxt=nxt;a[adr].val=key;
	}
	for(int i=adr;i!=-1;i=a[i].nxt)
		v.push_back(i);
	int l=v.size();//cout<<"l="<<l<<endl;
	int i;
	for(i=l-1;i>l/2;--i)
	{
		printf("%05d %d %05d\n",v[i],a[v[i]].val,a[v[l-i-1]].adr);
		printf("%05d %d %05d\n",v[l-i-1],a[v[l-i-1]].val,a[v[i-1]].adr);
	}
	if(i==l/2)
	{
		if(l&1)printf("%05d %d -1\n",v[i],a[v[i]].val);
		else{
			printf("%05d %d %05d\n",v[i],a[v[i]].val,a[v[l-i-1]].adr);
			printf("%05d %d -1\n",v[l-i-1],a[v[l-i-1]].val);
		}
	}
}

L2-028 秀恩爱分得快 (25 分)(模拟+两种方法)

【分析】一个大模拟题..? 一上来就想的是非常暴力的解法,虽然觉得可能会T,但是还是想试试,然后,100来行,很必然地超时了....

想过先把照片的数据先存起来,但是没有处理好,再次T 【就百度了一下 

先把照片信息存起来,记录每张照片的人数和各自的性别(注意0的处理,如果是-0那么性别是设置为-1的,所以要字符串读入);

然后输入情侣,再遍历照片信息,只记录有这两个人存在的照片

还要注意精度问题,除了之后要再乘上一个数,(不乘的话只有17分...和我T的代码一个分数诶..)

【代码】

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

const int maxn=1e3+10;
struct node{
	int k;
	int photo[maxn];
	int vis[maxn];
}a[maxn];
int sex[maxn];
int val1[maxn],val2[maxn];
int n,m;

void print(int x,int y)
{
	if(!x && sex[x]==-1)printf("-0 ");
	else printf("%d ",x*sex[x]);
	if(!y && sex[y]==-1)printf("-0\n");
	else printf("%d\n",y*sex[y]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;++i)
	{
		int k;scanf("%d",&k);
		a[i].k=k;
		for(int j=0;j<k;++j)
		{
			string str;cin>>str;
			int x=stoi(str);
			if(x<0)x=-x;
			a[i].photo[j]=x;
			a[i].vis[x]=1;
			if(str[0]=='-')sex[x]=-1;
			else sex[x]=1;
		}
	}
	string str1,str2;cin>>str1>>str2;
	int A=stoi(str1),B=stoi(str2);
	if(str1[0]=='-')A=-A,sex[A]=-1;
	else sex[A]=1;
	if(str2[0]=='-')B=-B,sex[B]=-1;
	else sex[B]=1;
	int f1=0,f2=0;
	for(int i=0;i<m;++i)
	{
		if(a[i].vis[A])
		{
			f1=1;
			for(int j=0;j<a[i].k;++j)
			{
				int x=a[i].photo[j];
				if(x!=A && sex[x]+sex[A]==0)
					val1[x]+=500*1.0/a[i].k;//,cout<<"1="<<x<<endl;
			}
		}
		if(a[i].vis[B])
		{
			f2=1;
			for(int j=0;j<a[i].k;++j)
			{
				int x=a[i].photo[j];
				if(x!=B && sex[x]+sex[B]==0)
					val2[x]+=500*1.0/a[i].k;//,cout<<"2="<<x<<endl;;
			}
		}
	}
	set<int>s1,s2;
	int maxx1=0,maxx2=0;
	for(int i=0;i<n;++i)
	{
		if(val1[i]>maxx1 && f1)
		{
			s1.clear();
			s1.insert(i);
			maxx1=val1[i];
		}
		else if(val1[i]==maxx1 && f1)
			s1.insert(i);
		if(val2[i]>maxx2 && f2)
		{
			s2.clear();
			s2.insert(i);
			maxx2=val2[i];
		}
		else if(val2[i]==maxx2 && f2)
			s2.insert(i);
	}
	if(maxx1==maxx2 && maxx1==val1[B] && maxx2==val2[A])print(A,B);//注意这里maxx1和maxx2不仅要相等而且是要对应彼此的 
	else
	{
		set<int>::iterator it;
		for(it=s1.begin();it!=s1.end();++it)
			print(A,*it);
		for(it=s2.begin();it!=s2.end();++it)
			print(B,*it);
	}
}
#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int f[2][maxn];
int e[maxn][510];
int sex[maxn],num[maxn];

void print(int x,int y)
{
	if(!x && sex[x]==-1)printf("-0");
	else printf("%d",x*sex[x]);
        printf(" ");
	if(!y && sex[y]==-1)printf("-0");
        else printf("%d",y*sex[y]);
        puts("");
}

int main()
{
	int n,m;scanf("%d%d",&n,&m);
	for(int i=0;i<=1;i++)for(int j=0;j<n;++j)f[i][j]=0;
	for(int k=1;k<=m;++k)
        {
    	    scanf("%d",&num[k]);
    	    for(int i=1;i<=num[k];++i)
	    {
		char s[10];scanf("%s",s);
		if(s[0]=='-')
                {
            	    e[k][i]=-atoi(s);
            	    sex[e[k][i]]=-1;
                }
                else
                {
            	    e[k][i]=atoi(s);
            	    sex[e[k][i]]=1;
                }
            }
        }
        string s1,s2;cin>>s1>>s2;
        int x=stoi(s1),y=stoi(s2);
        if(s1[0]=='-')x=-x,sex[x]=-1;
        else sex[x]=1;
        if(s2[0]=='-')y=-y,sex[y]=-1;
        else sex[y]=1;
        for(int k=1;k<=m;++k)
        {
    	    for(int i=1;i<=num[k];++i)
    		if(e[k][i]==x)
                {
            	    for(int j=1;j<=num[k];++j)
            	    {	
                        if(sex[e[k][i]]+sex[e[k][j]]==0)
            			f[0][e[k][j]]+=500.0/num[k]*100;
            		//cout<<e[k][j]<<","<<f[0][e[k][j]]<<"--\n";
           	    }
                }
            for(int i=1;i<=num[k];++i)
    		if(e[k][i]==y)
                {
                	for(int j=1;j<=num[k];++j)
            	        {
		    	    if(sex[e[k][i]]+sex[e[k][j]]==0)
                        	f[1][e[k][j]]+=500.0/num[k]*100;
            		//cout<<e[k][j]<<","<<f[1][e[k][j]]<<"-----\n";
            	        }
		} 
        }
        int maxx1=0,maxx2=0;
        for(int i=0;i<n;++i)maxx1=max(maxx1,f[0][i]);
        for(int i=0;i<n;++i)maxx2=max(maxx2,f[1][i]);
//	cout<<maxx1<<","<<maxx2<<endl;
	if(maxx1==f[0][y] && maxx2==f[1][x])print(x,y);
	else{
		for(int i=0;i<n;++i)
                    if(f[0][i]==maxx1 && sex[i]+sex[x]==0)print(x,i);
                for(int i=0;i<n;++i)
            	    if(f[1][i]==maxx2 && sex[y]+sex[i]==0)print(y,i);
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38735931/article/details/88363589