ACM 实验室2020.10.10天梯赛练习*2

7-10 链表去重 (25分)

题意:给出一组链表,删除数据重复的链表,输出去重后的链表和删除的链表。

题解:用结构体定义链表(包含链表的数据和下一个链表的地址),然后把输入的数据存到链表中,然后定义一个标记数组用来判断是否重复,把删除的链表存到a2数组,重复的链表存到a1数组,保存a2,a1

的长度,注意格式的输出。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int data;
    int next;
}l[100000];    
int vis[100000],a1[100000],a2[100000];//vis数组判断是否重复,a1去重完的链表,a2删除完的链表 
int main(){
    ios::sync_with_stdio(false);
    int add,n;
    int ad,da,ne;
    cin>>add>>n;
    for(int i=0;i<n;i++){
        cin>>ad>>da>>ne;//ad是地址 da是数据 ne是下个地址 
        l[ad].data=da;
        l[ad].next=ne;
    }
    int count1=0,count2=0;
    for(int i=add;i!=-1;i=l[i].next){//由它们的地址来找出数据是否相等
        if(vis[abs(l[i].data)]==0){
            vis[abs(l[i].data)]=1;
            a1[count1]=i;
            count1++;
        } 
        else{
            a2[count2]=i;
            count2++;
        } 
    }
    for(int i=0;i<count1;i++){//输出去重链表
        cout<<setw(5)<<setfill('0')<<a1[i]<<" "<<l[a1[i]].data<<" ";
        if(i!=count1-1){
            cout<<setw(5)<<setfill('0')<<a1[i+1]<<endl;
        }
        else{
            cout<<-1<<endl;
        }
    }
    for(int i=0;i<count2;i++){//输出删除的链表
        cout<<setw(5)<<setfill('0')<<a2[i]<<" "<<l[a2[i]].data<<" ";
        if(i!=count2-1){
            cout<<setw(5)<<setfill('0')<<a2[i+1]<<endl;
        }
        else{
            cout<<-1<<endl;
        }
    }
}

7-12 月饼 (25分)

题意:给出n个种类的月饼的价格和库存,判断卖出m个月饼最大的收益。

题解:贪心,根据每个不同种类的月饼的平均售价进行排序,然后从售价大的到小的进行判断,当m=0时结束循环即可。注意精度问题(比赛的时候差了3分一直看不出来- -)

#include<bits/stdc++.h>
using namespace std;
struct yb{
    double sj;
    double xql;
    double pjsj;
};
bool cmp(yb p,yb q){
    return p.pjsj>q.pjsj;
} 
int main(){
    int n,d;
    cin>>n>>d;
    yb a[n+10];
    for(int i=0;i<n;i++){
        cin>>a[i].xql;
    }
    for(int i=0;i<n;i++){
        cin>>a[i].sj;
        a[i].pjsj=double(a[i].sj*1.0/a[i].xql);
    }
    sort(a,a+n,cmp);
    double sum=0;
//    for(int i=0;i<n;i++){
//        cout<<a[i].pjsj<<endl;
//    }
    for(int i=0;i<n;i++){
        if(a[i].xql<=d){
        //    sum+=a[i].xql*a[i].pjsj;
            sum+=a[i].sj;
            d-=a[i].xql;
        }
        else{
            sum+=a[i].pjsj*d;
            break;
        }
        if(d<=0){
            break;
        }
    }
    printf("%.2lf
",sum);
}

7-5 6翻了 (15分)

题意:把这个字符串中6进行转换,如果6超过3个改成9,如果6超过9个改成27。

题解:就是记录每个6的个数存到数组中,然后进行遍历,如果遇到6判断这个6的字符串有多少个6然后进行输出6还是9还是27即可。

#include<bits/stdc++.h>
using namespace std;
int main(){
    string p;
    getline(cin,p);
    int g[10001];
    int count;
    int count1=0;
    for(int i=0;i<p.size();i++){
        if(p[i]=='6'){
            count=0;
            for(int j=i;p[j]=='6';j++){
                count++;
            }
            //cout<<count<<endl;
            g[count1]=count;
            count1++;
            i+=count;
        }
    }
    int count2=0;
    for(int i=0;i<p.size();i++){
        if(p[i]=='6'){
         if(g[count2]<=3){
             for(int j=0;j<g[count2];j++){
                 cout<<'6';
             }
             i+=g[count2];
             if(i<p.size()){
                 cout<<" ";
             }
             count2++;
         }
         else if(g[count2]>3&&g[count2]<=9){
              cout<<'9';
             i+=g[count2];
            if(i<p.size()){
                 cout<<" ";
             }
             count2++;
         }
         else if(g[count2]>9){
             cout<<"27";
             i+=g[count2];
            if(i<p.size()){
               cout<<" ";
             }
             count2++;
         }
      }
      else{
          cout<<p[i];
      }
    }
    cout<<endl;
}

7-11 部落 (25分)

题意:

输入每个部落的人数和序号,输出总人数和几个不交融的部落,再根据输入判断这2个人的部落是否有交集。

题解:根据并差集

#include<stdio.h>  
#include<iostream>  
#include<cstring>  
#define maxn 100000  
int f[maxn];  
using namespace std;  
void init()       //初始化函数因为没有告知人数所以就到maxn(作用:根都为自己)  
{  
    for(int i=1;i<=maxn;i++){  
        f[i]=i;  
    }  
}  
int getf(int a)     //找爹函数(找根)  
{  
    if(f[a]==a) //找到根(爹是自己~ ~),退出  
        return a;  
    else{  
        f[a]=getf(f[a]);//递归调用,找该树的根(祖先)  
        return f[a];  
    }  
}  
void merge(int v,int u) //找两个树的关系,如果祖先不一样(即没有关系,就合并,这里采用偏左原则)  
{  
    int t1,t2;  
    t1=getf(v);  
    t2=getf(u);  
    if(t1!=t2){  
        f[t2]=t1;   //让t1为t2的爹  
    }  
}  
int main()  
{  
    int n1,party[maxn],map[maxn];  
    int m,n=0,su=0,n2;  
    int i,a,b;  
    int sum=0;  
    cin>>m;  
    init();  
    memset(map,-1,sizeof(maxn)); //把map的值都设为-1,函数头文件#include<csting>,格式:memset(地址,需要设置成的值,sizeof);   
    while(m--)  
    {  
        cin>>n1;  
        n=n+n1;  
        for(i=1;i<=n1;i++){  
            cin>>party[i];  
            map[party[i]]=1; //输入时会用重复的,用标记数组map,进行标记,把输入树对应的值改为1  
            if(i-1)  
                merge(party[i-1],party[i]);  
        }  
    }  
    for(i=0;i<=n;i++){   //n没实际含义,只是圈定了一个范围,毕竟maxn太大  
        if(map[i]==1){  
        sum++;  
        }  
    }  
   for(i=1;i<=sum;i++){  
    if(f[i]==i){  
    su++;  
    }  
   }  
   cin>>n2;  
   cout<<sum<<" "<<su<<endl;  
   while(n2--){  
       cin>>a>>b;  
       if(getf(a)==getf(b))  
        cout<<"Y"<<endl;  
       else  
        cout<<"N"<<endl; 
   }
   return 0;
}

  

原文地址:https://www.cnblogs.com/liyongqi/p/13799023.html