2024CSP-J題解附原始碼T1-T3

zdragon的小迷弟發表於2024-10-26

T1

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

///T1題解
///輸入行數n
///輸入n行,每行一個字串,字串只有兩個字母組成,第一個字母是花色,第二個字母是點數。
///一副牌只有52種組合,因為map能去重,所以用map進行統計不同組合數即mp.size()
///結果為52-mp.size()

map<string,bool>mp;
int main() {
    int n;
    cin>>n;
    string s;
    for(int i = 0;i < n;i++) {
        cin>>s;
        mp[s] = true;
    }
    int ret = 52-mp.size();
    cout<<ret<<endl;
    return 0;
}
/*
4
DQ
H3
DQ
DT
49

1
SA
51
*/

T2

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

///T2題解
///有一張n*m的地圖,地圖上的位置要麼是空地、要麼是障礙物。
///有一個機器人,一開始機器人在某一個空地位置(x,y)
///機器人需要按照給定的方向d開始走路具體規則(規則看題目描述),求操作k次後機器人走過的不同空地位置數量
///機器人的每次操作有可能是走一步,有可能是右轉。只要機器人能往這個方向走則走一步操作,否則機器人需要右轉一次操作
///時間複雜度是O(k),k最大1e6,即O(n)
const int N = 1e3+5;
struct node {
    int x,y;
};
int n,m,k;
string s[N];
int dx[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; ///順序要根據題目寫
int vis[N][N]; ///標記走過的點,統計時能去掉重複走的點

bool check(int x,int y) {
    if(x >= 0 && x < n && y >= 0 && y < m && s[x][y]=='.'){ ///檢查要走的點在地圖上並且為空地
        return true;
    }
    return false;
}
int bfs(int x,int y,int d) {
    queue<node>qu;
    while(!qu.empty()) qu.pop(); ///清空佇列
    qu.push({x,y});
    fill(vis[0],vis[0]+N*N,0); ///多組資料,清空vis陣列
    vis[x][y] = 1;              ///起點標記
    int cnt =1;     ///包括起始位置;資料範圍k>=1
    while(!qu.empty()) {
        node now = qu.front();
        qu.pop();
        x = now.x;
        y = now.y;
        ///cout<<"goto "<<x<<" "<<y<<endl; ///輸出按題目要求走過的所有點,包括重複走的
        if(k==0) {          ///機器人操作完k次就可以返回答案了
            return cnt;
        }
        while(k) {  ///機器人只能操作k次
            k--;
            int xx = x+dx[d][0];    ///機器人下一步要走的位置是(xx,yy)
            int yy = y+dx[d][1];
            if(check(xx,yy)) {  ///檢查機器人想走的位置(xx,yy)能走
                qu.push({xx,yy});   ///位置(xx,yy)在地圖上並且為空地機器人就能走,需要入隊作為機器人下一步的位置
                if(vis[xx][yy] == 0) {  ///cnt統計機器人走過的不同位置數量,透過vis標記陣列能去掉機器人重複走過的位置
                    vis[xx][yy] = 1;
                    cnt++;
                }
                break;  ///只要機器人能走位置(xx,yy)就可以直接跳出迴圈,從佇列中獲取機器人的最新位置資訊即位置(xx,yy)。
            }
            else {
                ///cout<<"t r\n"; ///印表機器人右轉
                d = (d+1)%4;    ///機器人進行右轉
            }
        }
    }
    return cnt;  ///返回結果:機器人走過的不同位置數量(題目中說了包括起點)
}
void solve() {
    int x,y,d;
    cin>>n>>m>>k;   ///輸入地圖大小n*m和機器人操作次數k
    cin>>x>>y>>d;   ///輸入機器人起始位置(x,y)和方向d
    for(int i = 0;i < n;i++) {
        cin>>s[i];          ///輸入地圖
    }
    int ret = bfs(x-1,y-1,d);   ///呼叫bfs函式讓機器人進行k次操作並返回結果。
    cout<<ret<<"\n";        ///輸出結果
}
int main() {
    int T;
    cin>>T; ///輸入T
    while(T--) {///T組資料的出來
        solve();    ///呼叫solve函式處理每一組資料
    }
    return 0;
}
/*
樣例 1 輸入

2
1 5 4
1 1 2
....x
5 5 20
1 1 0
.....
.xxx.
.x.x.
..xx.
x....

樣例 1 輸出
3
13
*/

T3

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

///T3題解
///題目要求火柴組成的數字是最小的,那就儘可能把火柴組合成8,因為8使用的火柴數量最多
///特殊性質 A:保證 n 是 7 的倍數且 n ≥ 100。 20分
///特殊性質 B:保證存在整數 k 使得 n = 7k + 1,且 n ≥ 100。 30分
///送的50分,性質A的資料輸出全是數字8,8的數量為n/7;性質B的資料輸出:先輸出10之後全是8,輸出8的具體數量為(n-1-7)/7個。
///根據特殊性質資料提示,可以知道,組成的數字最小的方案:第一二位需要考慮,之後每一位只能是8
const int N = 1e3+5;
int a[40] = {-1,-1,1,7,4,2,6,8,10,18,22,20,28,68}; ///打表
void print8(int m) {
    for(int i = 0;i < m;i++) {
        cout<<8;
    }
    cout<<"\n";
    return;
}
void solve() {
    a[1] = -1; ///打表
    a[2] = 1;
    a[3] = 7;
    a[4] = 4;
    a[5] = 2;
    a[6] = 6; ///數字0也是用6根火柴,但不能有前導0,包括數字0
    a[7] = 8;
    int n;
    cin>>n;   ///輸入火柴數量n
    if(n < 7 ) { ///火柴數量小於7要打表。
        cout<<a[n]<<"\n";
    }
    else {
        switch(n%7) {
            case 0:                 ///火柴數量是7的倍數,
                print8(n/7);        ///全列印8並列印換行。
                break;
            case 1:                 ///火柴數量是7的倍數+1,
                cout<<10;           ///8根火柴組成的最小數是10,先列印10
                print8((n-1-7)/7);  ///列印8並列印換行
                break;
            case 2:                 ///火柴數量是7的倍數+2,
                cout<<18;           ///9根火柴組成的最小數是18,先列印18
                print8((n-2-7)/7);    ///全列印8並列印換行。
                break;
            case 3:                 ///火柴數量是7的倍數+3,
                if((n-10)/7) {   ///只考慮先輸出22,再輸出8個數。
                                    ///仔細觀察,2需要5根火柴,8需要7根火柴,0需要6根火柴
                    cout<<200;       ///2變0、8變0火柴數量是+1、-1,剛好抵消掉且可以使數字更小。
                    print8((n-10)/7-1);///因為把最前面的8換成了0,所以實數需要-1,列印8並列印換行
                }
                else {
                    cout<<22<<"\n"; ///10根火柴組成的最小數是22
                }
                break;
            case 4:                 ///火柴數量是7的倍數+4,
                cout<<20;            ///11根火柴組成的最小數是20,先列印20
                print8((n-4-7)/7);    ///全列印8並列印換行。
                break;
            case 5:                 ///火柴數量是7的倍數+5,
                cout<<28;           ///12根火柴組成的最小數是28,先列印28
                print8((n-5-7)/7);  ///列印8並列印換行
                break;
            case 6:                 ///火柴數量是7的倍數+6,
                cout<<68;           ///13根火柴組成的最小數是68,先列印68
                print8((n-6-7)/7);   ///全列印8並列印換行。
                break;
            default:
                break;
        }
    }
    return;
}

void st();
void bfs(int n,bool v,long long ans);
int main() {
    st();
    int T;
    cin>>T; ///輸入T
    while(T--) {///T組資料的出來
        solve();    ///呼叫solve函式處理每一組資料
    }
    return 0;
}
/*
【樣例 1 輸入】
5
1
2
3
6
18
【樣例 1 輸出】
-1
1
7
6
208
*/
/*
///打表check一下
int b[] = {-1,-1,1,7,4,2,0,8};
long long ret;
void dfs(int n,bool v,long long ans) {
    if(n==0) {
        ret = min(ans,ret);
        return;
    }
    if(n < 2) return;
    for(int i = 2;i <= 7;i++) {
        if(i > n) continue;
        if(i!=6) {
            dfs(n-i,1,ans*10+b[i]);
        }
        else {
            if(v) {
                dfs(n-i,v,ans*10);
            }
            else {
                dfs(n-i,1,ans*10+6);
            }
        }
    }
}
void st() {
    long long a = 1;
    for(int i = 1;i < 40;i++) {
        ret = 0x7fffffffffffffff;
        dfs(i,0,0);
        cout<<ret<<" "<<i<<" "<<i%7<<"\n";
    }
}
*/

相關文章