1. 程式人生 > >2018年新生中軟ACM程式設計大賽決賽 -題解

2018年新生中軟ACM程式設計大賽決賽 -題解

今天是院ACM新生賽的決賽啦, 題目出的比較難, 最多為9道
在這裡插入圖片描述
可以看到大部分還是WA一片

下面是題解, 有兩道題太過簡單 只提供了思路.

A 外幣兌換

//簽到題, 從下面幾個中選一個最大的, 相乘保留兩位小數就行了

B polygon

//其實就是求多邊形的內角和公式, 即使忘了應該想一下也就能推出來180*(n-2)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include
<stdlib.h>
#include<vector> #include<queue> #include<cmath> #include<map> usingnamespacestd; #definems(x,n)memset(x,n,sizeof(x)); typedef long long LL; const LL maxn=1e6+10; int main() { LL n; while(scanf("%lld",&n)!=EOF){ printf("%lld\n",(n-2)*180); } return 0; }

C 賭氣球

//完全根據來題意模擬就好了, 兩個細節注意一下, 有有可能玩不夠k次遊戲就結束啦, 遊戲結束前也要先輸出Not enough token.

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map> using namespace std; #define ms(x, n) memset(x,n,sizeof(x)); typedef long long LL; const LL maxn = 1e6+10; int T, k, n1, b, t, n2; int solve() { if(t > T) return -1; else if(n1 < n2){ if(b == 1){ T+=t; return 1; } else if(b == 0){ T-=t; T = max(0, T); return 0; } } else if(n1 > n2){ if(b == 0){ T+=t; return 1; } else if(b == 1){ T-=t; return 0; } } } int main() { cin >> T >> k; while(k--){ cin >> n1 >> b >> t >> n2; int flag = solve(); if(flag == -1) printf("Not enough tokens. Total = %d.\n",T); else if(flag == 1) printf("Win %d! Total = %d.\n",t,T); else if(flag == 0) printf("Lose %d. Total = %d.\n",t,T); if(T <= 0){ printf("Game Over.\n"); break; } } return 0; }

D 胡辣湯店

//斐波那契數列, 記得用long long

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;

int from,to;
LL cusNum[maxn];
void init()
{
    ms(cusNum,0);
    cusNum[1]=1,cusNum[2]=1;
    for(int i=3;i<=maxn;i++)
        cusNum[i]=cusNum[i-1]+cusNum[i-2];
}
int main()
{
    init();
    while(cin>>from>>to){
        LL sum=0;
        for(int i=from;i<=to;i++)
            sum+=cusNum[i];
        cout<<sum<<endl;
    }
    return 0;
}

E 害死人不償命的猜想

//資料量不大, 直接用遞迴演算法處理一下即可, 終止條件是n==1, 判讀奇偶對應處理即可

F 獎學金

//這道題是一道貪心演算法的最基礎的題目, 貪心演算法很好理解, 就算每次都處理最優解, 最終結果就一定是最優解, 這道題目就算每次都取最大能取的面額, 直到為0

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;


int money[]={1,5,10,20,50,100};
int main()
{
    int n,cont=0;
    cin>>n;

    while(n>0){
        for(int i=5;i>=0;i--)
            if(n>=money[i]){
                cont+=(n/money[i]);
                n%=money[i];
            }
    }
    cout<<cont<<endl;
}

G篩法

//這道題用到了篩法求素數(getPrime()函式), 而且要把素數提前預處完畢, 不能說用到一次再處理一次, 先測試一下可知n為104時最大取104729內的素數, 然後就求出104729以內的所有素數就好了, 之後遍歷迴圈輸出即可

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 104729;

bool isPrime[maxn];
int primeNum[maxn];
void getPrime()
{
    ms(primeNum, 0);
    for(int i = 2; i <= maxn; i++)
        if(!isPrime[i])
            for(int j = 2; i*j <= maxn; j++)
                isPrime[i*j] = 1;
    int tag = 1;
    for(int i = 2; i <= maxn; i++)
        if(!isPrime[i])
            primeNum[tag++] = i;
}
int main()
{
    getPrime();
    int m, n;
    cin >> m >> n;
    int tag = 0; //是否是第一個數
    for(int i = primeNum[m]; i <= primeNum[n]; i++){
        if(!isPrime[i]){
            if(tag==0) printf("%d",i), tag++;
            else printf(" %d",i), tag++;
            if(tag==10)
                printf("\n"), tag = 0;
        }
    }
	return 0;
}

H maze

//這道題是一道簡單搜尋的題目, 搜尋其實就算遞迴處理, 迷宮求解: 題意是n階方陣中判斷能否從左上角走到右下角, 走法是上下左右.

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 35;
int maze[maxn][maxn], vis[maxn][maxn]; //vis表示是否走過
int T, n;
int action[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
int flag;
void Dfs(int x, int y)
{ //迷宮走到x,y時
    if(x==n && y == n){
        flag = 1;
        return; //1表示可走
    }

    for(int i = 0; i < 4; i++){
        int tx = x+action[i][0], ty = y+action[i][1];
        if(!vis[tx][ty] && maze[tx][ty] && tx>=1 && tx<=n && ty>=1 && ty<=n){
            vis[tx][ty] = 1;
            Dfs(tx, ty);
            vis[tx][ty] = 0; //回溯法處理
        }
    }
    return; //0表示不可走
}
int main()
{
    scanf("%d",&T);
    while(T--){
        memset(maze, 0, sizeof(maze)); //初始化
        memset(vis, 0, sizeof(vis));
        flag = 0;

        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d",&maze[i][j]);

        vis[1][1] = 1;
        Dfs(1, 1); //初始狀態

        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

I 開心報道

//最簡單的動態規劃問題 - 01揹包問題, 定義dp[i][j]作為一個狀態, 然後根據題意尋得狀態轉移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1e5+10;

int W, n, w[maxn], v[maxn];
int dp[110][maxn]; //在前i個物品中選容量不超過j時的最大價值
int main()
{
    cin >> n >> W;
    for(int i = 1; i <= n; i++)
        cin >> w[i] >> v[i];

    //動態規劃
    ms(dp, 0);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= W; j++){
            if(j >= w[i])
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
            else
                dp[i][j] = dp[i-1][j];
        }


    cout << dp[n][W] << endl;

    return 0;
}

J 階乘的和

//高精度模板即可

#include <algorithm> // max
#include <cassert>   // assert
#include <cstdio>    // printf,sprintf
#include <cstring>   // strlen
#include <iostream>  // cin,cout
#include <string>    // string類
#include <vector>    // vector類

using namespace std;

struct BigInteger {
    typedef unsigned long long LL;

    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;

    BigInteger &clean() {
        while (!s.back() && s.size() > 1)s.pop_back();
        return *this;
    }

    BigInteger(LL num = 0) { *this = num; }

    BigInteger(string s) { *this = s; }

    BigInteger &operator=(long long num) {
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        } while (num > 0);
        return *this;
    }

    BigInteger &operator=(const string &str) {
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for (int i = 0; i < len; i++) {
            int end = str.length() - i * WIDTH;
            int start = max(0, end - WIDTH);
            sscanf(str.substr(start, end - start).c_str(), "%d", &x);
            s.push_back(x);
        }
        return (*this).clean();
    }

    BigInteger operator+(const BigInteger &b) const {
        BigInteger c;
        c.s.clear();
        for (int i = 0, g = 0;; i