PTA-寒假算法集训第一周

1.13-1.16做过的题
题目:6-2 多项式求值(15分)
简单

double f(int n,double a[],double x)
{
    double ans=0;
    double tx=1;
    for(int i=0;i<=n;i++)
    {


        ans=ans+a[i]*tx;
        tx=tx*x;
    
    }
    return ans;
}

题目:L1-087 机工士姆斯塔迪奥(20分)
要考虑重合的格子

#include<stdio.h>
int main()
{
    int n = 0;
    int m = 0;
    int q = 0;
    scanf("%d %d %d",&n,&m,&q);
    int i = 0;
    int t = 0;
    int c = 0;
    int countrow = 0;
    int countcol = 0;
    int row[100001]={0};
    int col[100001]={0};
    for(i=0;i<q;i++)
    {
        scanf("%d %d",&t,&c);
        if(t==0)
        {
           if(row[c]!=1)
           {
                countrow++;
                 row[c]=1;
           }
        }
        else
        {
            if(col[c]!=1)
            {
                countcol++;
                col[c]=1;
            }
        }
    }
    printf("%d",m*n-countrow*m-countcol*n+(countrow*countcol));
    return 0;
}

题目:7-35 城市间紧急救援(25分)
迪杰斯特拉最短路

#include <stdio.h>
#include <stdlib.h>
#define INF 0xFFFFFF
int n,m,s,d;
int dis[500];//最短路数组
bool check[500]={false};//是否被选择过的结点数组
int countn[500]={0};//最短路径数量
int weith[500];//每个结点的救援队数量
int w[500];//从出发点到支援点的救援队总数
int graph[500][500];//邻接矩阵
int v[500];//结点的最短后继
void Dijkstra(){
    int i,j;
    w[s]=weith[s];
    dis[s]=0;
    countn[s]=1;
    for(i=0;i<n;i++){
        int minx,minn=INF;
        for(j=0;j<n;j++){
            if(dis[j]<minn&&check[j]!=true){//找出当前的最短点
                minx=j;
                minn=dis[j];
            }
        }
        check[minx]=true;
        for(j=0;j<n;j++){
            if(graph[minx][j]>0){
                if(minn+graph[minx][j]<dis[j]){
                    dis[j]=minn+graph[minx][j];
                    w[j]=weith[j]+w[minx];
                    v[j]=minx;//当前点的最短路径的前一个结点
                    countn[j]=countn[minx];
                }
                else if(minn+graph[minx][j]==dis[j]){
                     countn[j]=countn[minx]+countn[j];
                    if(w[minx]+weith[j]>w[j]){
                        v[j]=minx;
                        w[j]=w[minx]+weith[j];
                       
                    }
                }
            }
        }
    }
    //for(i=0;i<n;i++)
    //    printf("%d ",countn[i]);
}
int main(){
    scanf("%d%d%d%d",&n,&m,&s,&d);
    int i,j;
    for(i=0;i<n;i++)
        scanf("%d",&weith[i]);
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            dis[j]=INF;
        }
    }
    for(i=0;i<m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        graph[a][b]=c;
        graph[b][a]=c;
    }
    Dijkstra();
    int t[500];
    i=0;
    for(j=d;j>=0;j=v[j]){
        t[i++]=j;
        if(j==0)
            break;
    }
    printf("%d %d\n",countn[d],w[d]);
    for(i--;i>=0;i--){
        printf("%d",t[i]);
        if(i!=0)
            printf(" ");
    }
    return 0;
}

题目:7-35 有理数均值(20分)

#include <bits/stdc++.h>
using namespace std;
int f(int p,int q){
    if (q==0) return p;
    int r = p%q;
    return f(q,r);
}
int main()
{
int n;
scanf("%d",&n);
int i,sum=0,pr=1,a,b,t;
for(i=0;i<n;i++)
{
    scanf("%d/%d",&a,&b);
    if(a==0 || b==0)
    continue;
    sum=sum*b+a*pr;
    pr*=b;
    if(i==n-1)
    pr*=n;
    t=f(sum,pr);
    sum/=t;
    pr/=t;
} 
if(sum==0){
cout<<0<<endl;
}else if(pr!=1){
printf("%d/%d",sum,pr);
}else{
printf("%d",sum);
}
}

题目:L2-023 图着色问题(25分)
邻接矩阵

#include <bits/stdc++.h>
using namespace std;
int d[510][510];
int c[510];
int main()
{
    int V,E,K;
    cin>>V>>E>>K;
   
    for(int i=1;i<=E;i++)
    {
        int a,b;
        cin>>a>>b;
        d[a][b]=d[b][a]=1;
    }
    int M;
    cin>>M;
    while(M--)
    {
       
        bool ans=true;
        set<int> s;
        for(int i=1;i<=V;i++)
        {
            scanf("%d",&c[i]);
            s.insert(c[i]);
           
        }
        for(int i=1;i<=V;i++)
        {
            for(int j=1;j<=V;j++)
                if(d[i][j]&&c[i]==c[j])
                    ans=false;
        }
        if(s.size()!=K)
           cout<<"No"<<endl;
       else if(ans)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
}

题目:L2-028 秀恩爱分得快(25分)

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

int n,m,k;
vector<int>a,b;//a存女生,b存男生(用于输入的时候计算亲密度)
set<int>A,B;//A存女生,B存男生(用于最后输出的时候遍历找出最大亲密度)用set可以忽略那些重复出现的人
double g[1005][1005], maxn[1005];//g[][]存放每一对异性的亲密度,maxn存放一个人对另外异性的最大亲密度

int main()
{
	cin>>n>>m;
	string s;
	while(m--)
	{
		cin>>k;
		a.clear();
		b.clear();
		for(int i=0; i<k; i++)
		{
			cin>>s;
			if(s[0] == '-')//女生情况
			{
				a.push_back(abs(stoi(s)));
				A.insert(abs(stoi(s)));
			}
			else//男生
			{
				b.push_back(stoi(s));
				B.insert(abs(stoi(s)));
			}
		}
		for(int i=0; i<a.size(); i++)//计算每一张照片中所有异性的亲密的
		{
			for(int j=0; j<b.size(); j++)
			{
				g[a[i]][b[j]] += 1.0/k;
				g[b[j]][a[i]] += 1.0/k;
				if(maxn[a[i]] < g[a[i]][b[j]])//找出每个人最大的亲密的
				    maxn[a[i]] = g[a[i]][b[j]];
			    if(maxn[b[j]] < g[b[j]][a[i]])
			        maxn[b[j]] = g[b[j]][a[i]];
            }
		}
	}
	string s1, s2;
	cin>>s1>>s2;//情侣的编号
	int aa = abs(stoi(s1));
	int bb = abs(stoi(s2));
	if(maxn[aa] == g[aa][bb] && maxn[bb] == g[bb][aa])//如果情侣之间的亲密度都是最大的
	{
		cout<<s1<<" "<<s2;
		return 0;
	}
	if(s1[0] == '-')//如果先输入女生
	{
		for(auto p:B)
		{
			if(maxn[aa] == g[aa][p])
			    cout<<s1<<" "<<p<<endl;
		}
	}
	else 
	{
		for( auto p:A)
		{
			if(maxn[aa] == g[aa][p])
			    cout<<s1<<' '<<'-'<<p<<endl; 
		}
	}
	if(s2[0]=='-')//如果后输入女生
    {
        for(auto p:B)
            if(maxn[bb]==g[bb][p])
                cout<<s2<<' '<<p<<endl;
    }
    else
    {
        for(auto p:A)
            if(maxn[bb]==g[bb][p])
                cout<<s2<<' '<<'-'<<p<<endl;
    }
	return 0;
}


题目:7-2 一元多项式的乘法与加法运算(15分)

#include<stdio.h>
 
int main() {
	int a[1001] = {0},b[1001] = {0};
	int k1,k2;
	scanf("%d",&k1);
	for(int i = 0 ; i < k1;i ++) {
		int xishu,zhishu;
		scanf("%d %d",&xishu,&zhishu);
		a[zhishu] = xishu;
	}
	scanf("%d",&k2);
	for(int i = 0; i < k2; i++) {
		int xishu,zhishu;
		scanf("%d %d",&xishu,&zhishu);
		b[zhishu] = xishu;
	}
	int cnt = 0;
	int c[10003] = {0};
	for(int i = 0 ; i <=1000; i++) {
		for(int j = 0; j <= 1000 ; j ++) {
			int xishu1 = a[i] * b[j];
			int zhishu1 = i + j;
			if(xishu1 != 0) {
				c[zhishu1] += xishu1;
				cnt++;
			}
		}
	}
	int flag = 1;
	if(cnt == 0) {
		printf("0 0\n");
	} else {
		for(int i = 10000; i >= 0 ; i-- ) {
			if(c[i] != 0 ){
				if(flag == 0) {
					printf(" ");
				}
				printf("%d %d",c[i],i);
				flag = 0;
			}
		}
		printf("\n");
	}
	
	flag = 1;
	cnt = 0;
	for(int i = 0; i <=1000; i++) {
		a[i] += b[i];
		if(a[i] != 0) {
			cnt++;
		}
	}  
	if(cnt == 0) {
		printf("0 0");
	} else {
		for(int i = 1000; i >= 0 ; i-- ) {
			if(a[i] != 0 ){
				if(flag == 0) {
					printf(" ");
				}
				printf("%d %d",a[i],i);
				flag = 0;
			}
		}
	}
	return 0;
}

题目:7-52 两个有序链表序列的交集
最后一个测试点有坑
求交集函数:set_intersection()

#include <bits/stdc++.h>
using namespace std;
int main()
{
   vector<int> v1;
   vector<int> v2;
   vector<int> ans;
   int n;
   while(cin>>n,n!=-1)
   {
       v1.push_back(n);
   }
   while(cin>>n,n!=-1)
   {
       v2.push_back(n);
   }
   set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),back_inserter(ans));
    int f=0;
    if(ans.size()==0)
    {
        cout<<"NULL";
        return 0;
    }
        
    for(auto i:ans)
    {
        if(f==0)
            cout<<i,f=1;
        else
            cout<<' '<<i;
    }
   
}

题目:7-3 树的同构(25分)
树是否同构的判别就是父节点是否相同

#include <bits/stdc++.h>
using namespace std;
int main(void)
{
    short N1,i;
    short father1[N1];
    char data1[N1];
    short node1[26],node2[26];
    short appear1[26],appear2[26];       //出现的字符
    short flag=1;               //表示是否为同构树
    
    cin>>N1;
    for(i=0;i<26;i++)
      appear1[i]=appear2[i]=0;      //都没有出现

    for(i=0;i<N1;i++)
        father1[i]=i;      //先初始化为自己

    for(i=0;i<N1;i++){
        char m0,m1,m2;
        cin>>m0>>m1>>m2;
        data1[i]=m0;      //第i号节点的字符
        node1[m0-'A']=i;      //某个字符属于的节点编号
        appear1[m0-'A']=1;
        if('-'!=m1)
          father1[m1-'0']=i;
        if('-'!=m2)
          father1[m2-'0']=i;
    }      //记录父节点以及每个节点的字母

    short N2;
    cin>>N2;
    short father2[N2];
    char data2[N2];

    for(i=0;i<N2;i++)
      father2[i]=i;

    if(N1!=N2)
      flag=0;
    else{
      for(i=0;i<N2;i++){
        char m0,m1,m2;
       cin>>m0>>m1>>m2;
        data2[i]=m0;
        node2[m0-'A']=i;
        appear2[m0-'A']=1;
        if('-'!=m1)
          father2[m1-'0']=i;
        if('-'!=m2)
          father2[m2-'0']=i;
      }

      for(i=0;i<26;i++){     //检索26个字符
        if(!appear1[i]&&!appear2[i])
          continue;          //该字符不在树中
        if(!appear1[i]*appear2[i]){
          flag=0;
          break;
        }     //说明出现的字符不同
        if(data1[father1[node1[i]]]!=data2[father2[node2[i]]]){
          flag=0;
          break;
        }
      }
    }

    if(flag)
      printf("Yes");
    else
      printf("No");

    return 0;
}



题目:7-25 朋友圈(25分)
并查集

#include <bits/stdc++.h>
using namespace std;
int N,M;
int f[30010];
int cnt[30010];

int find(int x)
{
    if(f[x]==-1)
        return x;
    else 
        return f[x]=find(f[x]);
}

int fin(int x,int y)
{
    int a=find(x),b=find(y);
    if(a!=b)
        f[b]=a;
}

int main()
{
    cin>>N>>M;
    memset(f,-1,sizeof f);
    while(M--)
    {
        int Mi,x,y;
        cin>>Mi;
        for(int i=1;i<=Mi;i++)
        {
            cin>>y;
            if(i==1)
                x=y;
            else
                fin(x,y);
        }
    }
    for(int i=1;i<=N;i++)
        cnt[find(i)]++;
    int ans=0;
    for(int i=1;i<=N;i++)
        ans=max(ans,cnt[i]);
    cout<<ans;
}

题目:L2-041 插松枝(25分)
栈、队列

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,k,x;
    cin>>n>>m>>k;
    stack<int> box;
    queue<int> push;
    vector<int> tree;
    while(n--)
    {
        cin>>x;
        push.push(x);
        
    }
   
    while(1)
    {
       if((push.size()==0&&box.size()==0)||tree.size()==k||box.size()==m&&(push.size()==0||push.front()>tree.back())||push.size()==0&&box.top()>tree.back())
        {
            for(int j=0;j<tree.size();j++)
                if(j>0)
                    cout<<" "<<tree[j];
                else
                    cout<<tree[j];
            cout<<endl;
            tree.clear();
        }
        if(push.size()==0&&box.size()==0)//推送器和盒子里面都没有了,结束
            break;
        if(box.size()>0&&(tree.size()==0||box.top()<=tree.back()))//盒子里面有并且树是空的或者盒子里面的满足
        {
            tree.push_back(box.top());
            box.pop();
        }
        else if(push.size()>0&&(tree.size()==0||push.front()<=tree.back()))//推送器上有并且树是空的或者推送器上的满足
        {
            tree.push_back(push.front());
            push.pop();
        }
        else if(tree.size()>0&&push.front()>tree.back())//树上已经有了并且推送器上的大于树上的,把推送器上的放入盒子中
        {
            box.push(push.front());
            push.pop();
        }
       }
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戴戴.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值