1. 程式人生 > 實用技巧 >10.10天梯賽補題

10.10天梯賽補題

7-1估值一億的AI核心程式碼(20分) 題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648
解題思路:字串函式應用
string.find("xx")
string::npos
s.replace(位置,長度,替換為什麼)
string.erase(pos,n)          //刪除從pos開始的n個字元    string.erase(0,1);   刪除第一個字元
string.erase(pos)           //刪除pos處的一個字元(pos是string型別的迭代器)
string.erase(first,last)    //刪除從first到last中間的字元(first和last都是string型別的迭代器)
ispunct()    //檢測一個字元是否是標點符號,返回真or假
string.find("xx",從什麼位置開始)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
static const int MAX_N = 15;
string str;
bool judge(int pos, int p, int len) {
    /*越界判斷*/
    if(pos + p < len && pos - 1 >= 0) return (!isalnum(str[pos - 1]) && !isalnum(str[pos + p]));
    
else if(pos - 1 >= 0) return (!isalnum(str[pos - 1])); else if (pos + p < len) return (!isalnum(str[pos + p])); else return true; } int main() { int t; scanf("%d", &t); getchar(); while (t--) { getline(cin, str); cout << str << endl;
int len = str.length(); while (len > 1 && str[0] == ' ') { //去掉行前空格 str.erase(0, 1); len--; } int i = len - 1; while (i >= 0 && str[i] == ' ') { //去掉行末空格 str.erase(i, 1); --i; } i = 0; len = str.length(); for (; i < len; ++i) { while (str[i] == ' ') { //去掉單詞間的多餘空格 if (i + 1 < len && !isalnum(str[i + 1])) { //這裡不能直接判斷是空格,因為是標點符號的話,空格也需要去掉 str.erase(i, 1); len--; } else break; } if(str[i] != 'I' && str[i] >= 'A' && str[i] <= 'Z') //轉小寫 str[i] += 32; else if (str[i] == '?') str[i] = '!'; } for (i = 0; i < len; ++i) { if (str[i] == 'I' && judge(i, 1, len)) str.replace(i, 1, "you"); /*擷取字元,注意判斷,不然會陣列越界*/ else if (i + 1 < len && str.substr(i, 2) == "me" && judge(i, 2, len)) str.replace(i, 2, "you"); else if (i + 6 < len && str.substr(i, 7) == "can you" && judge(i, 7, len)) str.replace(i, 7, "I can"); else if (i + 8 < len && str.substr(i, 9) == "could you" && judge(i, 9, len)) str.replace(i, 9, "I could"); len = str.length(); } printf("AI: "); cout << str << endl; } return 0; }
估值一億的AI核心程式碼

7-3N個數求和(20分)

題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648

在實驗室做出來了就不多贅述了

#include<stdio.h>
#include<math.h>
#include<string.h>
#define Q 1000000007
#define ll long long int
int ys(ll a,ll b) {
    ll i;
    while(b!=0) {
        i=a%b;
        a=b;
        b=i;
    }
    return a;
}
int main() {
    ll a[150];
    ll b[150];
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++) {
        scanf("%lld/%lld",&a[i],&b[i]);
    }
    ll sum1=a[0];
    ll sum2=b[0];
    int s=ys(sum1,sum2);
    sum1/=s;
    sum2/=s;
    for(int i=1; i<n; i++) {
        s=ys(sum2,b[i]);
        sum1=sum1*(b[i]/s)+a[i]*(sum2/s);
        sum2=sum2*b[i]/s;
        s=ys(sum1,sum2);
        sum1/=s;
        sum2/=s;
    }
    ll t=sum1/sum2;
    sum1=sum1%sum2;
    if(sum2<0) {
        sum1=-sum1;
        sum2=-sum2;
    }
    if(sum1==0)
        printf("%lld\n",t);
    else if(t==0)
        printf("%lld/%lld\n",sum1,sum2);
    else
        printf("%lld %lld/%lld\n",t,sum1,sum2);
    return 0;
}

7-9名人堂與代金券(25分)

題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648

解題思路:採用結構體,注意相同的排名按照字母表排序,後續的排名順延就行

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int rank;//排名; 
    string str;
    int grade;
}person[10005];
bool cmp(struct node p1,struct node p2)
{
    if(p1.grade != p2.grade)
    {
        return p1.grade>p2.grade;//非升序排列;
    }
    else if(p1.grade == p2.grade)
    {
        return p1.str<p2.str;//按賬號的字母升序輸出;
    }
}
int main()
{
    int n,g,k,i,j,sum=0,count=1;//n指的是學生總數,g指的是等級分界線,k指的是進入名人堂的最低名次;
    cin>>n>>g>>k;
    for(i=0;i<n;i++)
    {
        cin>>person[i].str>>person[i].grade;
        if(person[i].grade>=g){
            sum = sum + 50;
        }
        else if(person[i].grade>=60&&person[i].grade<g){
            sum = sum + 20;
        }
    }
    //PAT 代金券的總面值
    cout<<sum<<endl;
    sort(person,person+n,cmp);
    person[0].rank = 1;//
    count=1;
    //當成績相同時,排名一樣
    for(i=1;i<n;i++)
    {
        count++;
        if(person[i].grade == person[i-1].grade)
        {
            person[i].rank = person[i-1].rank;    
        }
        else
        {
            person[i].rank = count;    
        }    
    } 
    //輸出名次在<=k範圍之內的同學資訊!!!!
    for(i=0;i<n;i++) 
    {
        if(person[i].rank<=k)
        {
            cout<<person[i].rank<<" "<<person[i].str<<" "<<person[i].grade<<endl;
        }
    }
    return 0;
}

7-10 連結串列去重 (25分)

題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648

解題思路:題目要求刪除鍵值的絕對值有重複的結點,然後先輸出刪除後的連結串列,再輸出被刪除的連結串列

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5;
struct Node{
    int address;
    int key;
    int next;
    int num;
}node[maxn];
bool vis[maxn];
bool cmp(Node a,Node b){
    return a.num<b.num;
}
int main()
{
    int head,n,a;
    scanf("%d%d",&head,&n);
    int k1=0,k2=0;
    for(int i=0;i<maxn;i++){
        node[i].num=2*maxn;
    }
    for(int i=0;i<n;i++){
        scanf("%d",&a);
        scanf("%d%d",&node[a].key,&node[a].next);
        node[a].address=a;
             }
    for(int i=head;i!=-1;i=node[i].next){
        if(!vis[abs(node[i].key)]){
            vis[abs(node[i].key)]=true;
            node[i].num=k1;
            k1++;
        }else{
            node[i].num=maxn+k2;
            k2++;
        }
    }
    sort(node,node+maxn,cmp);
    int k=k1+k2;
    for(int i=0;i<k;i++){
        if(i!=k1-1&&i!=k-1){
            printf("%05d %d %05d\n",node[i].address,node[i].key,node[i+1].address);
        }else{
            printf("%05d %d -1\n",node[i].address,node[i].key);
        }
    }
    return 0;
}

7-11部落(25分)

題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648

解題思路:用了並查集,存點的時候有一點是用了set存點,直接去除重複點來計算共有多少結點。易錯易超時的地方就是find函式一定要用優化版本的find函式,不然會超時。

#include <bits/stdc++.h>
using namespace std;
int fa[10005], flag[10005];
set<int> s;

int find(int x){
    if(fa[x]==x){
        return x;
    }else{
        return fa[x] = find(fa[x]);
    }
}

void Union(int a, int b){
    int fathera = find(a);
    int fatherb = find(b);
    if(fathera!=fatherb){
        fa[fatherb] = fathera;
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int n, num=0, q, q1, q2;
    cin>>n;
    for(int i=0;i<10005;i++){
        fa[i] = i;
        flag[i] = 0;
    }
    for(int i=0;i<n;i++){
        int k, p[10005];
        cin>>k>>p[0];
        s.insert(p[0]);
        for(int j=1;j<k;j++){
            cin>>p[j];
            s.insert(p[j]);
            Union(p[0], p[j]);
        }
    }
    set<int>::iterator it;
    for(it=s.begin();it!=s.end();it++){
        if(flag[find(*it)]==0){
            num++;
            flag[find(*it)] = 1;
        }
    }
    cout<<s.size()<<" "<<num<<endl;
    cin>>q;
    for(int i=0;i<q;i++){
        cin>>q1>>q2;
        if(find(q1)==find(q2)){
            cout<<"Y"<<endl;
        }else{
            cout<<"N"<<endl;
        }
    }
    return 0;
}

7-12月餅(25分)

題目連結:https://pintia.cn/problem-sets/1314102638464851968/problems/1314102915477659648

解題思路:用了結構體,計算一下每種月餅的單價從高往低誰單價高先賣誰,資料用double,注意小數點。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct mooncake      //用結構體可以方便對單價排序,分開定義陣列會打亂順序
{
    double knum;       //都有可能是小數
    double pnum;
    double anum;
};
bool cmp(mooncake a,mooncake b)
{
    return a.anum>b.anum;
}
int main()
{
    int N,D;
    cin>>N>>D;
    mooncake mk[1001];
    for(int i=0;i<N;i++)
        cin>>mk[i].knum;
    for(int i=0;i<N;i++)
        cin>>mk[i].pnum;
    for(int i=0;i<N;i++)
        mk[i].anum=mk[i].pnum/mk[i].knum;
    sort(mk,mk+N,cmp);

    int i=0;
    double sum=0;
    while(D!=0)
    {
        if(D<=mk[i].knum)
        {
            sum+=mk[i].anum*D;
            D=0;
        }
        else
        {
            sum+=mk[i].pnum;
            D-=mk[i].knum;
        }
        i++;
    }
    printf("%.2f",sum);     //輸出帶格式,使用printf更方便
}