PTALV2习题集(题解与坑点分析)

文章目录

  • L2-013 红色警报 (25 分)(图的连通性)
  • L2-023 图着色问题 (25 分)(图的连通性)
  • L2-025 分而治之 (25 分)(链接表存图)
  • L2-014 列车调度 (25 分)
  • L2-015 互评成绩 (25 分)
  • L2-016 愿天下有情人都是失散多年的兄妹 (25 分)
  • L2-018 多项式A除以B (25 分)
  • L2-019 悄悄关注 (25 分)(map的应用)
  • L2-020 功夫传人 (25 分)(广搜)
  • L2-026 小字辈 (25 分)(广搜)
  • L2-031 深入虎穴 (25 分)(广搜)
  • L2-021 点赞狂魔 (25 分)(set应用)
  • L2-029 特立独行的幸福 (25 分)(set与map的应用)
  • L2-022 重排链表 (25 分)(模拟)

L2-013 红色警报 (25 分)(图的连通性)

传送门

题解传送门:
根据图的连通性,搜索图

#include
using namespace std;

int n,m,k;
bool g[550][550];
int ans,in[550];
bool v[550];

void dfsg(int x){
	v[x]=1;
	for(int i=0;i<n;i++){
		if(g[x][i]&&!v[i]){
			dfsg(i);
		}
	}
	return;
}

int dfs(){
	memset(v,0,sizeof v);
	int cnt=0;
	for(int i=0;i<n;i++){
		if(!v[i]){
			dfsg(i);
			cnt++;
		}
	}
	return cnt;
}

bool check(int x){
	for(int i=0;i<n;i++){
		if(g[x][i]) g[x][i]=g[i][x]=0;
	}
	int cnt=dfs();
	//cout<<"cnt= "<
	if(cnt>ans+1){
		ans=cnt;
		return 0;
	}
	else{
	ans=cnt;
	return 1;	
	}
}

int main(){
	cin>>n>>m;
	while(m--){
		int a,b;
		cin>>a>>b;
		in[a]++,in[b]++;
		g[a][b]=g[b][a]=1;
	}
	ans=dfs();
	cin>>k;
	m=k;
	while(k--){
		int x;
		cin>>x;
		if(!check(x)){
			cout<<"Red Alert: ";
			cout<<"City "<<x<<" is lost!"<<endl;
		}
		else cout<<"City "<<x<<" is lost."<<endl;
	}
	
	if(m==n) cout<<"Game Over."<<endl;
	
	return 0;
}

L2-023 图着色问题 (25 分)(图的连通性)

#include
using namespace std;

bool g[550][550],A=0;
int a[550];
int n,e,k;
bool v[550];
bool shu[550];

void dfs(int x){
    v[x]=1;
	for(int i=1;i<=n;i++){
        if(g[x][i])
           if(a[x]==a[i]) A=0;
		if(g[x][i]&&!v[i]){
			dfs(i);
		}
	}
	return;
}

bool check(){
	A=1;
	for(int i=1;i<=n;i++){
		if(!v[i]) dfs(i);
	}
	return A;
}
int main(){
	cin>>n>>e>>k;
	
	for(int i=0;i<e;i++){
		int a,b;
		cin>>a>>b;
		g[a][b]=g[b][a]=1;
	}
	
	int m;
	cin>>m;
	while(m--){
        memset(v,0,sizeof v);
        memset(shu,0,sizeof shu);
        int cnt=0;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(!shu[a[i]]) cnt++;
			shu[a[i]]=1;
		}
		if(cnt!=k){
			cout<<"No"<<endl;
			continue;
		}
		if(check()) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
} 

L2-025 分而治之 (25 分)(链接表存图)

#include
using namespace std;

const int N=10086;
int h[N],e[N*2],ne[N*2],idx;
int a[N];
int n,m;

void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

bool check(){
	bool A=1;
	for(int i=1;i<=n;i++){
		if(a[i]) continue;
		for(int j=h[i];j!=-1;j=ne[j]){
			int k=e[j];
			if(!a[k]){
				A=0;
				break;
			}
		}
	}
	return A;
}

int main(){
	cin>>n>>m;
	memset(h,-1,sizeof h);
	while(m--){
		int a,b;
		cin>>a>>b;
		add(a,b),add(b,a);
	}
	
	int k;
	cin>>k;
	while(k--){
		int v,x;
		cin>>v;
		memset(a,0,sizeof a);
		for(int i=0;i<v;i++) 
		  cin>>x,a[x]=true;
		if(check()) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
    if(n==1) cout<<"YES"<<endl;
	return 0;
}

L2-014 列车调度 (25 分)

题解:
根据题意,每个通道都是一个升序序列,由于不需要考虑记录的数,我们只需要用set记录每次的最小值,如果当前数比set里面的数都大,则讲这个数插入到set里面

#include
using namespace std;

set<int>::iterator it;
int main(){
	int n;
	cin>>n;
	set<int> st;
	while(n--){
		int k;
		cin>>k;
		it=st.lower_bound(k);
		if(it!=st.end()){
			st.erase(it);
		}
		st.insert(k);
	}
	cout<<st.size();
	
	return 0;
}

L2-015 互评成绩 (25 分)

题解:
根据题意做就是了,没有什么难度,但是有坑点,如果我们把所有数记录下来最后再遍历输出会超时,必须用priority_queue q;边计算边记录,保持队列长度在题目要求范围内

#include
using namespace std;

int a[11];
int main(){
	int n,m,k;
	cin>>n>>m>>k;
	priority_queue<double,vector<double>,greater<double> > q;
	while(n--){
		double ans=0;
		for(int i=0;i<m;i++) cin>>a[i];
		sort(a,a+m);
		for(int i=1;i<m-1;i++) ans+=a[i];
		ans=ans/(double)(m-2);
		if(q.size()>=k){
			if(q.top()<ans) q.pop();
			else continue;
		}
		q.push(ans);
	}
	
	printf("%.3lf",q.top());
	q.pop();
	while(!q.empty()){
		printf(" %.3lf",q.top());
		q.pop();
	}
	
	return 0;
}

L2-016 愿天下有情人都是失散多年的兄妹 (25 分)

#include
using namespace std;

struct guanxi{
	int fa=0,mom=0;
	char sex;
}g[100086];

void check(int x,set<int> &st,int cnt){
	if(cnt>5||x==0) return;
	st.insert(x);
	check(g[x].fa,st,cnt+1);
	check(g[x].mom,st,cnt+1);
}

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		int id,fa,mom;
		char sex;
		cin>>id>>sex>>fa>>mom;
        //cout<
		g[id].sex=sex;
		if(fa!=-1){
			g[id].fa=fa;
			g[fa].sex='M';
		}
		if(mom!=-1){
			g[id].mom=mom;
			g[mom].sex='F';
		}
	}
	
	int k;
	cin>>k;
	while(k--){
		set<int> u,v;
		int x,y;
		cin>>x>>y;
		if(g[x].sex==g[y].sex){//同性
			cout<<"Never Mind"<<endl;
			continue;
		}
		check(x,u,1);
		check(y,v,1);
        bool A=0;
		for(auto i=u.begin();i!=u.end();i++){
			if(v.find(*i)!=v.end()){//判断出现在x的关系谱中是否也出现在了y的关系普中
				cout<<"No"<<endl;
				A=1;break;
			}
		}
		if(!A) cout<<"Yes"<<endl;
	}
	
	return 0;
}

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

题解:
模拟多项式相除

#include
#include
#include
#include
using namespace std;
double  c1[100005], c2[100005], c3[100005];
int f(double a[], int e)//判断多项式非0的项数
{
	int ret = 0;
	for (int i = e; i >= 0; i--)
	{
		if (fabs(a[i]) >= 0.05)
			ret++;
	}
	return ret;
}
void solve(double a[], int e)//打印多项式
{
	cout << f(a, e);
	if (f(a, e) == 0)
		cout << " 0 0.0";//零多项式
	else
	{
		for (int i = e; i >= 0; i--)
		{
			if (fabs(a[i]) >= 0.05)
				printf(" %d %.1f", i, a[i]);
		}
	}
	cout << endl;
}
int main()
{
	int n;
	while (cin >> n)
	{
		int maxe1, maxe2;//A B的最大指数
		for (int i = 0; i < n; i++)
		{
			int e;
			double c;
			cin >> e >> c;
			if (i == 0)
			{
				maxe1 = e;
			}
			c1[e] = c;//指数为e,系数为c
		}
		int m;
		cin >> m;
		for (int i = 0; i < m; i++)
		{
			int e;
			double c;
			cin >> e >> c;
			if (i == 0)
			{
				maxe2 = e;
			}
			c2[e] = c;
		}
		int d = maxe1 - maxe2;
		while (maxe2 <= maxe1)
		{
			double v = c1[maxe1] / c2[maxe2];
			c3[maxe1 - maxe2] = v;//商 
			for (int i = maxe1,j = maxe2; i >= 0 && j >= 0; j--, i--)
			{
				c1[i] -= c2[j] * v;//余数  指数相同的对应位置系数相减
			}
			while (fabs(c1[maxe1]) < 0.05)//四舍五入为0的项去掉
				maxe1--;
			
		}
		solve(c3, d);//打印
		solve(c1, maxe1);
	}
 
	system("pause");
	return 0;
}

L2-019 悄悄关注 (25 分)(map的应用)

#include
using namespace std;

map<string,double> mp,mpp;

int main(){
	int n,k,m=0;
	cin>>n;
	string s;
	while(n--){
		cin>>s;
		mp[s]=0;
	}
	
	cin>>n;
	double ans=0;
	for(int i=0;i<n;i++){
		cin>>s>>k;
		if(mp.find(s)!=mp.end()) ans+=k,k=0,m++;
		mpp[s]=k;
	}
	ans=ans/(double)m;
	
	bool A=1;
	for(auto i=mpp.begin();i!=mpp.end();i++){
		if(i->second>ans) A=0,cout<<i->first<<endl;
	}
	if(A) cout<<"Bing Mei You";
	return 0;
}

L2-020 功夫传人 (25 分)(广搜)

#include
using namespace std;

const int N=1e5+100;
vector<vector<int>>v;
int n;
double z,r;
double dedao[N];
double ans=0;

void bfs(){
	queue<int> q;
	q.push(0);
	
	while(!q.empty()){
		int k=q.front();
		q.pop();
		//cout<
		for(int i=0;i<v[k].size();i++){
			int m=v[k][i];
			q.push(m);
			if(dedao[m]>1) dedao[m]=dedao[m]*dedao[k]*(1-r*0.01),ans+=dedao[m]*z;
			else dedao[m]=dedao[k]*(1-r*0.01);
		}
	}
	
}

int main(){	
	cin>>n>>z>>r;
	v.resize(n);
    if(n==1){
        int k,x;
        cin>>k>>x;
        cout<<z*x;
        return 0;
    }
	for(int i=0;i<n;i++){
		dedao[i]=1;
		int k,x;
		cin>>k;
		if(k==0){
			cin>>x;
			dedao[i]=(double)x;
		}else{
			while(k--) cin>>x,v[i].push_back(x);
		}
	}
	
	bfs();
	cout<<(long long)ans;
	return 0;
}

L2-026 小字辈 (25 分)(广搜)

#include
using namespace std;

vector<vector<int>> v;
int vis[200086];
int maxx=0,ans=0;
void bfs(int x){
	queue<int> q;
	q.push(x);
	vis[x]=1;
	
	while(!q.empty()){
		int k=q.front();
		q.pop();
		
		for(int i=0;i<v[k].size();i++){
			int m=v[k][i];
			q.push(m);
			vis[m]=vis[k]+1;
            //cout<
			if(vis[m]>maxx) ans=0,maxx=vis[m];
			if(vis[m]==maxx) ans++;
		}
	}
}
int main(){
	int n,x,f;
	cin>>n;
	v.resize(n+1);
	for(int i=1;i<=n;i++){
		cin>>x;
        if(n==1){
            cout<<1<<endl;
            cout<<1;
            return 0;
        }
		if(x==-1){
			f=i;
			continue;
		}
		v[x].push_back(i);
	} 
	bfs(f);
	cout<<maxx<<endl;
	for(int i=1;i<=n;i++){
		if(vis[i]==maxx){
			cout<<i;
			ans--;
			if(ans) cout<<" ";
		}
	}
}

L2-031 深入虎穴 (25 分)(广搜)

#include
using namespace std;

int n;
vector<vector<int>> v;
int in[100086];
int maxx=0;
void bfs(int x){
	queue<int> q;
	q.push(x);
	
	while(!q.empty()){
		int k=q.front();q.pop();
		if(q.size()==0) maxx=k;
        //cout<
		for(int i=0;i<v[k].size();i++){
			int m=v[k][i];
           // cout<
			q.push(m);
		} 
	}
}

int main(){
	cin>>n;
	v.resize(n+1);
	for(int i=1;i<=n;i++){
		int k,x;
		cin>>k;
		for(int j=0;j<k;j++){
			cin>>x;
			v[i].push_back(x);
			in[x]++;
		}
	}
	
	int fa;
	for(int i=1;i<=n;i++){
		if(in[i]==0){
			fa=i;break;
		}
	}
	
	bfs(fa);
	cout<<maxx;
	return 0;
}

L2-021 点赞狂魔 (25 分)(set应用)

#include
using namespace std;

int n;
struct pep{
	string s;
	int num,cs;
}p[1086];

bool cmp(pep x,pep y){
	if(x.num==y.num) return x.cs<y.cs;
	return x.num>y.num; 
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		string s;
		cin>>s;
		int k,x,v;
		cin>>k;
		set<int> st;v=k;
		while(k--) cin>>x,st.insert(x);
		p[i]={s,st.size(),v};
	}
	for(int i=n;i<3;i++){
		p[i]={"-",0,0};
	}
	
	sort(p,p+n,cmp);
	cout<<p[0].s;
	for(int i=1;i<3;i++) cout<<" "<<p[i].s;
	return 0;
}

L2-029 特立独行的幸福 (25 分)(set与map的应用)

#include
using namespace std;

int a,b;
bool v[10086];

bool isprim(int x){
	for(int i=2;i*i<=x;i++)
		if(x%i==0) return 0;
	return 1;
}
int main(){
	cin>>a>>b;
	map<int,int> an;
	for(int i=a;i<=b;i++){
		int n=i;
		set<int> st;
		while(n!=1){
		   int ans=0;
		   while(n){
		   	int k=n%10;
		   	ans+=k*k;
		   	n/=10;
		   }
		   if(st.find(ans)!=st.end()) break;
		   st.insert(ans);
            v[ans]=1;
		   n=ans;
	}
	if(n==1) an[i]=st.size();
	}
	bool A=0;
	for(auto it=an.begin();it!=an.end();it++){
        if(v[it->first]) continue;
		if(isprim(it->first)) cout<<it->first<<" "<<2*it->second<<endl,A=1; 
		else cout<<it->first<<" "<<it->second<<endl,A=1; 
	}
    
    if(!A) cout<<"SAD";
	return 0;
}

L2-022 重排链表 (25 分)(模拟)

#include
using namespace std;

struct link{
	int date,next;
}links[100086],lik[100086];
int srt,n;
int k;
int a[100086];

int main(){
	cin>>srt>>n;
	for(int i=0;i<n;i++){
		int add,date,next;
		cin>>add>>date>>next;
		links[add]={date,next};
	}
	
    int i=0;
	while(srt!=-1){
		int date=links[srt].date;
		lik[i].date=date;
		lik[i].next=srt;
		srt=links[srt].next;
        i++;
	}
	
    n=i;
	int j=0;
	for(int i=0;i<n/2;i++){
		a[j++]=n-1-i;
		a[j++]=i;
	}
    if(n%2) a[j]=n/2;
	//for(int i=0;i
	for(int i=0;i<n;i++){
		int k=a[i];
		if(i==0) printf("%05d %d ",lik[k].next,lik[k].date);
		else if(i==n-1) printf("%05d\n%05d %d ",lik[k].next,lik[k].next,lik[k].date);
		else printf("%05d\n%05d %d ",lik[k].next,lik[k].next,lik[k].date);
	}
    cout<<-1;
	return 0;
}

你可能感兴趣的:(PAT,深度优先,算法,c++)