1. 程式人生 > >2017藍橋杯C++A組題解集合

2017藍橋杯C++A組題解集合

總結:藍橋杯的題目大多數都是暴利或者dfs、bfs解出來的,注意往這上面思考

下面是賽題的連結:https://wenku.baidu.com/view/951dab772a160b4e767f5acfa1c7aa00b52a9d2d.html

然後就是部分試題的答案,有些轉載的,僅供參考

一、迷宮

四、方格分割

/*
仔細觀察樣例資料可以發現,要滿足題目所需要求,只需要剪下的線關於圖案的中點中心對稱。
那麼我們可以將格子格子之間接壤的看作邊,邊與邊相交的看作點。則從(3,3)點出發,
找一條邊到達圖案的外圈,不過值得注意的是,從(3,3)出發的是看錯兩個人出發,兩個人的線路一直是對稱。
所以dfs中標記的時候要一步標記兩個。最後的結果要除以4,因為題目中說要旋轉對稱的是同一種。
*/
#include<bits/stdc++.h>
using namespace std;
int visited[10][10];
int ans=0;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
void dfs(int x,int y)
{
    if(x==0||y==0||x==6||y==6)
    {
        ans++;
        return;
    }
    for(int i=0;i<4;i++)
    {
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        if(visited[nx][ny])
            continue;
        visited[nx][ny]=1;
        visited[6-nx][6-ny]=1;
        dfs(nx,ny);
        visited[nx][ny]=0;
        visited[6-nx][6-ny]=0;
    }
}
int main()
{
    memset(visited,0,sizeof visited);
    visited[3][3]=1;
    dfs(3,3);
    printf("%d %d\n",ans,ans/4);
}

五、字母組串

f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1)

六、最大公共子串

a[i-1][j-1]+1

七、正則問題

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

string str;
int pos, len;
int dfs()
{
    int xnum = 0, res = 0;
    while (pos < len) {
        if (str[pos] == '(') {
            pos++;
            xnum += dfs();
        }
        else if (str[pos] == ')') {
            pos++;
            break;
        }
        else if (str[pos] == '|') {
            pos++;
            res = max(xnum, res);
            xnum = 0;
        }
        else {
            pos++;
            xnum++;
        }
    }
    res = max(xnum, res);
    return res;
}
int main()
{
    cin >> str;
    int ans = 0;
    len = str.length(), pos = 0;
    ans = dfs();
    cout << ans << endl;
    return 0;

}

八、包子湊數

這道題用到了數論的知識:本題要判斷能不能湊出c個包子就相當於判斷ax+by=c這個方程的是否有解,根據數論知識我們知道gcd(a,b)如果不等於1,那麼湊不出來的c就有無窮多個,程式碼中的求gcd的函式應該熟記,然後else裡面的for迴圈就是動態規劃求出所有引數能湊出的包子數

#include <cstdio>  
using namespace std;

int gcd(int a, int b) 
{
    if (b == 0) 
        return a;
    return gcd(b, a%b);
}

int unit[110], n;
const int N = 10010;
bool sign[N];

int main(){
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d", &unit[i]);
        int g = unit[0];
        for (int i = 1; i < n; i++)
            g = gcd(g, unit[i]);
        if (g != 1){
            printf("INF\n");
        }
        else{
            sign[0] = true;
            for (int i = 0; i < n; i++){
                for (int j = 0; j + unit[i] < N; j++)
                    if (sign[j])
                        sign[j + unit[i]] = true;
            }
            int count = 0;
            for (int i = 0; i < N - 1; i++){
                if (sign[i] == false)
                    count++;
            }
            printf("%d\n", count);
        }
        return 0;
}

九、分巧克力

#include <cstdio>  
using namespace std;

int n, k, length[100010], wide[100010];

bool chocolate(int x)  //判斷正方形邊長x時能不能切出大於等於K塊
{
    int num = 0, a, b, i;
    for (i = 0; i<n; i++)  //n塊巧克力一共能切出num塊分給小朋友們
    {
        a = length[i] / x;
        b = wide[i] / x;
        num += a*b;
    }
    if (num >= k)
        return true;
    return false;
}
int main()
{
    int i, low, high;
    while (scanf("%d%d", &n, &k) != EOF)
    {
        low = 1;
        high = 100001;
        for (i = 0; i<n; i++)
            scanf("%d%d", &length[i], &wide[i]);
        while (low<high-1)   //二分搜尋找出正方形巧克力邊長的最大值
        {
            int mid = (low + high) / 2;
            if (!chocolate(mid))
                high = mid;
            else
                low = mid;
        }
        printf("%d\n", low);
    }
    return 0;
}