2021年合肥學院程序設計競賽


2021年合肥學院校賽題解

A.我愛合院

思路

​ 直接輸出"HFUU"即可。

代碼:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    cout << "HFUU";
    return 0;
}

B.簡單的工資發放問題

思路

第一天的工資為1,后面兩天的工資為2, 2,后面三天的工資為3,3,3......
數據范圍為1 - 10000,方法很多, 我們可以先預處理出每天的工資,然后循環一次累加每天的工資即可。時間復雜度O(n)

代碼

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 10010;

LL a[N];
int n;
int main()
{
    int n;
    scanf("%d", &n);
    int qwq = 0;
    int flag = 1;
    for(int i = 1; i <= n; i ++ )
    {
        a[i] = flag;
        ++ qwq;
        if(qwq == flag)
        {
            flag ++;
            qwq = 0;
        }
    }
    LL ans = 0;
    for(int i = 1; i <= n; i ++ ) ans += a[i];
    printf("%lld",ans);
    return 0;
}

C.簡單的計算幾何問題

思路

本題我們可以對所有的點求一個凸包,答案就是凸包的周長。

代碼

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define x first
#define y second

using namespace std;
const int  N = 10010;

typedef pair<double,double> PDD;
int n;
PDD q[N];
int stk[N];
bool st[N];

PDD operator-(PDD a, PDD b)
{
    return {a.x - b.x, a.y - b.y};
}

double cross(PDD a, PDD b)
{
    return a.x * b.y - b.x * a.y;
}

double area(PDD a, PDD b, PDD c)
{
    return cross(b - a, c - a);
}

double get_dist(PDD a, PDD b)
{
    double xx = a.x - b.x;
    double yy = a.y - b.y;
    return sqrt(xx * xx + yy * yy);
}

double Andrew()
{
    sort(q + 1, q + 1 + n);
    int top = 0;
    for(int i = 1; i <= n; i ++ )
    {
        while(top >= 2 && area(q[stk[top - 1]], q[stk[top]], q[i]) <= 0)
        {
            if(area(q[stk[top - 1]], q[stk[top]], q[i]) < 0)
                st[stk[top -- ]] = false;
            else top --;
        }
        stk[ ++ top] = i;
        st[i] = true;
    }
    st[1] = false;
    for(int i = n; i >= 1; i -- )
    {
        if(st[i]) continue;
        while(top >= 2 && area(q[stk[top - 1]], q[stk[top]], q[i]) <= 0)
        {
            if(area(q[stk[top - 1]], q[stk[top]], q[i]) < 0)
                st[stk[top -- ]] = false;
            else top --;
        }
        stk[++ top] = i;
        st[i] = true;
    }
    double res = 0;
    for(int i = 2; i <= top; i ++ )
        res += get_dist(q[stk[i]], q[stk[i - 1]]);
    return res;
}

int main()
{
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++ ) scanf("%lf %lf",&q[i].x, &q[i].y);
    double res = Andrew();
    printf("%.2lf", res);
    return 0;
}

D.簡單的理財問題

思路:

本題是純模擬題。
整個過程是確定的,從前往后依次模擬整個流程即可。

模擬過程中記錄如下幾個值:

total: 存在姐姐那里的總錢數;
remain: bs當前剩在自己手里的錢數;
cur:讀入的值,表示當前這個月的生活開銷

依次枚舉每個月,對於當前這個月,首先判斷總共能拿到的錢數是否夠用,即判斷:

cur + 300 >= cur是否成立;
如果夠用,則將整百部分交給姐姐,自己剩下最多兩位數的錢。

最后的總錢數是:total * 12 + remain

代碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int total = 0, remain = 0;
    for (int i = 1; i <= 12; i ++ )
    {
        int cur;
        cin >> cur;
        if (remain + 300 < cur)
        {
            total = -i;
            break;
        }
        remain += 300 - cur;
        total += remain / 100 * 120;
        remain %= 100;
    }

    if (total >= 0) total += remain;

    cout << total << endl;

    return 0;
}

E.簡單的路徑規划問題

思路

裸的最短路問題,方法很多,套朴素Dijkstra都能過,堆優化的當然更好。
朴素Dijkstra的時間復雜度 \(O(n^2)\)

優化的Dijkstra的時間復雜度為\(O(nlogn)\)

代碼

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510;

int n, m;
int g[N][N];
int dist[N];
bool st[N];

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    for (int i = 0; i < n - 1; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);

        st[t] = true;
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    memset(g, 0x3f, sizeof g);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);

        g[a][b] = min(g[a][b], c);
    }

    printf("%d\n", dijkstra());

    return 0;
}

F.簡單的字符串問題

思路:

本題要求長度大於\(1\)且最短的回文串,只有三種情況:
\(1\).字符串里面出現連續兩個相同的字符 , \(exp: .....aa.....\) 答案是$ 2 $
\(2\).字符串中出現長度為3的回文串,例如: $...qwq... $答案是 \(3\)
\(3\).字符串中只有長度為1的回文串例如:\(abcdefg\),答案是 \(-1\)
其余的回文串如果存在則一定長於第一第二種情況,所以答案只有\(2, 3, -1\)
時間復雜度為\(O(n)\)\(n\)為字符串的長度。

代碼:

#include <cstring>
#include <iostream>

using namespace std;

string s;

int main()
{
    cin >> s;
    int len = s.length();
    for(int i = 1; i < len; i ++ )
    {
        if(s[i] == s[i - 1]) {
            printf("2\n");
            return 0;
        }
    }
    for(int i = 1; i < len; i ++ )
    {
        if(s[i - 1] == s[i + 1] && i + 1 < len){
            printf("3\n");
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}

G.簡單的排序問題

思路:

本題的思路很明顯,先把所有的時間段排個序,然后選擇時間段較長的即可,排序的話大部分排序方式都能過,冒泡也能過。
時間復雜度是關於你的排序方式,冒泡為\(O(n^2)\)或者快排是\(O(nlogn)\)

代碼:

#include <stdio.h>
#define N 10010
int main()
{
    int n;
	int a[N];
	scanf("%d",&n);
	for(int i = 1; i<= n; i ++ ) scanf("%d",&a[i]);
	int temp, i, j;

	for (i = 1; i <= n; i++)    //進行9次比較
		for (j = 1; j <= n - i; j++)   //在每次中進行10-i-1次比較
			if (a[j] > a[j + 1])      //按升序排序,降序用<
			{
				temp = a[j + 1];      //交換相鄰的兩個元素
				a[j + 1] = a[j];
				a[j] = temp;
			}

    int sum = 0;
	for (i = n / 2 + 1; i <= n; i++)  sum += a[i];
	printf("%lld", sum);
}

H.簡單的桌游問題

思路:

題意可以理解成不能出現邊長都為1的三角形路徑,根據這個要求,可以發現,當將一個元素作為起點,遍歷剩余的棋子作為一個個終點,這樣的連接方式是符合題意要求的。同時,為了保證答案的最大化,我們可以將更多的棋子作為起點方,剩余的棋子當作終點方,顯然當起點和終點的棋子差距最小時,答案是最大的,所以本題可以等價成左右兩排數求最多的連接數。
時間復雜度為\(O(1)\).

代碼:

#include <bits/stdc++.h>
using namespace std;
 
typedef long long LL;
const int mod = 998244353;
 
int main() {
    int n;
    while (cin >> n)
    cout << (n / 2) * (n - n / 2) << endl;
    return 0;
}

I.簡單的數據結構問題

思路:

本題的每組數據的答案都在一個不斷更新的長度為一整天的數組中,注意到每次輸入時的ti是遞增的,所以可以類比成一個滑動的窗口不斷單調滑動,所以本題我們需要用到隊列來處理滑動窗口,用隊列中隊頭和隊尾的更新來模擬窗口的滑動,在滑動時不斷更新數組儲存的國籍數據。
時間復雜度\(O(K)\)

代碼:

#include<iostream>
using namespace std;
int s,i,n,t,k,r,w[100001],x[300002],y[300002];

int main(){
    cin>>n;
    while(n--){
        cin>>t>>k;
        while(k--){
            y[++r]=t;cin>>x[r];
            if(!w[x[r]])s++;
            w[x[r]]++;
        }
        while(t-y[i]>=86400)
            if(!--w[x[i++]])s--;
        cout<<s<<endl;
    }
    return 0;
}

J.合院生日快樂

思路:

輸出$ n - 40 + 2020$即可

代碼:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;
    cin >> n;
    cout << n  - 40 + 2020 << endl;
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM