2016年藍橋杯B組C/C++決賽題解

2016年第七屆藍橋杯B組C/C++決賽題解

2016年藍橋杯B組C/C++決賽題目(不含答案)html

1.一步之遙

枚舉解方程,或者套模板解線性方程c++

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

int main(){
    int ans = 0x3f3f3f3f;
    for(int a=0;a<=100;a++){
        for(int b=0;b<=100;b++){
            if(97*a - 127*b == 1){
                ans = min(ans,a+b);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
} 
//97

2.湊平方數

思路:
分紅幾組? k組 1 ~ 10;
每組:dfs搜索0~9這幾個沒用過的數;
if 徹底平方數
1.x+1
2.繼續加值 (0不能做爲第一個數 單獨考慮)
到了k組 先對結果排序存到vector數組中 再set去重(由於遞歸回溯 結果有大量重複)數組

注意:必須用long long...用int會出錯 由於int的取值範圍爲:-2147483648 ~ 2147483647spa

網上有全排列後 再dfs的方法,這樣不用再回溯打亂順序,博客地址:https://blog.csdn.net/riba2534/article/details/72480145.net

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

typedef long long ll;
int vis[15];
ll a[15];
vector<ll> v;
int vis2[10];
int k;
int ans = 0;
set<vector<ll> > se;

inline bool check(ll x){
    if(x == 9814072356){
        int eeeeee = 1;
    }
    double d = sqrt(x);
    return d == (ll)d;
}

//由於遞歸回溯有大量重複  改爲set去重 
void dfs(int x,ll cur){
    if(x == k){
        for(int i=0;i<10;i++){
            vis2[i] = 0;
        }
        for(int i=0;i<k;i++){
            ll d = a[i];
            if(d == 0) vis2[d] = 1;
            else{
                while(d){
                    vis2[d%10] = 1;
                    d = d/10;
                }
            }
        }
        for(int i=0;i<=9;i++){
            if(!vis2[i]) return;
        }
        for(int i=0;i<k;i++) v.push_back(a[i]);
        sort(v.begin(),v.end());
        if(se.find(v) == se.end()){
            for(int i=0;i<k;i++) cout<<v[i]<<" ";
            cout<<endl;
            se.insert(v);
        }
        v.clear();
        ans++;
        return;
    }
    
    for(int i=0;i<=9;i++){
        if(!vis[i]){
            vis[i] = 1;
            if(cur == 0 && i == 0){//若是是以0開頭 而且當前搜索的是一個新的分組(cur值爲0) 就直接搜索下一組 
                a[x] = 0;
                dfs(x+1,0);
                vis[i] = 0;
                continue;
            }
            ll num = cur*10+i;
            if(check(num)){
                a[x] = num;
                dfs(x+1,0);
            } //搜索下一分組 
            dfs(x,cur*10+i);//繼續搜索當前分組
            vis[i] = 0;
        }
    }
}

int main(){
    //freopen("out1.txt","w",stdout);
    //枚舉分組的次數 
    for(k = 1;k <= 10;k++){
        memset(vis,0,sizeof(vis)); 
        dfs(0,0);
    }
    cout<<ans<<endl;
    cout<<se.size()<<endl;
    return 0;
} 
//3085
//300

3.棋子換位

輸出結果
手算
判斷二者不一樣點
嘗試給出答案。。 就這樣作
思路:交換的兩邊不同,才能跳
答案:valid(data, i+dd+dd) &&valid(data, i-dd) && data[i-dd] == data[i+dd+dd]code

4.機器人塔

直接dfs搜索了,初步估計能過30%數據htm

思路:dfs搜索blog

首先理解題意:搭人梯 總人數確定是按1 + 2 + 3 + 4 +.....+n 這種數據類型來給的 題目寫了保證數據合理。
咱們能夠提早預處理 給定的人數應該搭人梯 共幾層 好比樣例:1 2 就是2層 樣例:3 3就是3層 知足等差數列 1 + 2 + 3,咱們根據等差數列性質求出下面代碼的belong數組 有sum我的時對應的層數排序

belong[a+b] 算出 等於共k層,固然用等差數列公式開方也直接能算的,不用再預處理了。。。。。。
用等差數列公式開方,上面過程能夠不看遞歸

主要是dfs:
隨後 dfs搜索每一層:dfs(int x,int cur,int numa,int numb) 參數含義:第x層 當前層的第cur個位置 使用a的數量numa 使用b的數量numb
按題目條件dfs填充a[x][cur]就能夠了

剪枝後也只能太小數據

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

const int maxn = 510;
int belong[maxn*maxn];
int a[maxn][maxn];
int n,m;
int ans = 0;
int k;

void dfs(int x,int cur,int numa,int numb){
    if(x == k){ //出口:最後一層只能放置一個 容易判斷 
        if(numa == n-1 && numb == m){
            if((a[x-1][1] == 1 && a[x-1][2] == 1) || (a[x-1][1] == 2 && a[x-1][2] == 2)){
                ans++;
            }
        }
        if(numb == m-1 && numa == n){
            if((a[x-1][1] == 1 && a[x-1][2] == 2) || (a[x-1][1] == 2 && a[x-1][2] == 1)){
                ans++;
            }
        }
        return;
    }
    
    int idx = k-x+1;
    if(x == 1){//第一層能夠隨意放 
        for(int i=cur;i<idx;i++){ //每一層能夠放idx個 
            if(numa + 1 <= n){
                a[x][i] = 1;
                dfs(x,cur+1,numa+1,numb);
                a[x][i] = 0;
            }
            if(numb + 1 <= m){
                a[x][i] = 2;
                dfs(x,cur+1,numa,numb+1);
                a[x][i] = 0;
            }
        }
        if(cur == idx){
            if(numa + 1 <= n){
                a[x][cur] = 1;
                dfs(x+1,1,numa+1,numb);
                a[x][cur] = 0;
            }
            if(numb + 1 <= m){
                a[x][cur] = 2;
                dfs(x+1,1,numa,numb+1);
                a[x][cur] = 0;
            }

        }
    }else{ //非第一層 受題目條件限制放置 
        for(int i=cur;i<idx;i++){ //每一層能夠放idx個 
            if((a[x-1][i] == 1 && a[x-1][i+1] == 1) || (a[x-1][i] == 2 && a[x-1][i+1] == 2)){
                if(numa + 1 <= n){
                    a[x][i] = 1;
                    dfs(x,cur+1,numa+1,numb);
                    a[x][i] = 0;
                }
            }
            if((a[x-1][i] == 1 && a[x-1][i+1] == 2) || (a[x-1][i] == 2 && a[x-1][i+1] == 1) ){
                if(numb + 1 <= m){
                    a[x][i] = 2;
                    dfs(x,cur+1,numa,numb+1);
                    a[x][i] = 0;
                }
            }
        }
        if(cur == idx){
            if((a[x-1][cur] == 1 && a[x-1][cur+1] == 1) || (a[x-1][cur] == 2 && a[x-1][cur+1] == 2)){
                if(numa + 1 <= n){
                    a[x][cur] = 1;
                    dfs(x+1,1,numa+1,numb);
                    a[x][cur] = 0;
                }
            }
            if((a[x-1][cur] == 1 && a[x-1][cur+1] == 2) || (a[x-1][cur] == 2 && a[x-1][cur+1] == 1) ){
                if(numb + 1 <= m){
                    a[x][cur] = 2;
                    dfs(x+1,1,numa,numb+1);
                    a[x][cur] = 0;
                }
            }
        }
    }
}

void init(){
    for(int i=1;i<=200;i++){
        int sum = 0;
        for(int j=1;j<=i;j++){
            sum += j;
        }
        belong[sum] = i;
    }
}

int main(){
    init();
    cin>>n>>m;
    k = belong[n+m]; 
    dfs(1,1,0,0);
    cout<<ans<<endl;
    return 0;
}

5.廣場舞

想到思路了,可是作起來仍是挺麻煩的,不寫了
提供幾條資料
百度:計算幾何 判斷點與多邊形的關係
這題題解博客(不保證準確性 可是博主寫的很詳細能看懂得) https://blog.csdn.net/codeswarrior/article/details/80397275

6.生成樹計數

不寫了

相關文章
相關標籤/搜索