藍橋杯寒假訓練----2

大提琴的聲音就像一條河,左岸是我無法忘卻的回憶,右岸是我值得緊握的璀璨年華,中間流淌的,是我年年歲歲淡淡的感傷。

                                                     李白打酒

話說大詩人李白,一生好飲,幸好他從不開車。

一天,他提着酒壺,從家裏出來,酒壺中有酒 2 鬥,他邊走邊唱:

無事街上走,提壺去打酒。

逢店加一倍,遇花喝一斗。

這一路上,他一共遇到店 mm 次,遇到花 nn 次,已知最後一次遇到的是花,他正好把酒喝光了。

請你計算李白遇到店和花的次序,可以把遇店記爲 aa,遇花記爲 bb。

例如:這一路上,他一共遇到店 55 次,遇到花 1010 次,已知最後一次遇到的是花,他正好把酒喝光了。則:babaabbabbabbbb 就是合理的次序。像這樣的答案一共有多少呢?請你計算出所有可能方案的個數(包含題目給出的)。

Input

輸入一個整數 TT,包括 TT 組數據,每組數據包括遇到店的次數 mm,花的次數 nn。

Output

對於每組數據,輸出李白遇到店和花的可能次序的個數。

Example

input

Copy

1
5 10

output

Copy

14
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int ct,T,m,n;
void dfs(int sum,int fg,int store,int flower)
{
    if(store==0&&flower==0&&fg==1)//最後一次遇到的是花
    {
        if(sum==0)//恰好把酒喝光
        {
            ct++;
            return ;
        }
        else
            return ;
    }
    else
    {
        if(store>0&&sum>0)//有酒經過商店
            dfs(sum*2,0,store-1,flower);
        if(flower>0&&sum>0)//有酒經過花店
            dfs(sum-1,1,store,flower-1);
    }
}
int main()
{
    cin>>T;
    while(T--)
    {
        ct=0;
        cin>>m>>n;
        dfs(2,0,m,n);
        cout<<ct<<endl;
    }
    return 0;
}

                                                     九宮重排

如下面第一個圖的九宮格中,放着 1 到 8 的數字卡片,還有一個格子空着。與空格子相鄰的格子中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。

我們把第一個圖的局面記爲:12345678.

把第二個圖的局面記爲:123.46758

顯然是按從上到下,從左到右的順序記錄數字,空格記爲句點。

本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出 −1−1。

Input

輸入第一行包含九宮的初態,第二行包含九宮的終態。

Output

輸出最少的步數,如果不存在方案,則輸出 −1−1。

Example

input

Copy

12345678.
123.46758

output

Copy

3
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int fx[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int jc[]= {1,1,2,6,24,120,720,5040,40320,362880}; //表示階乘運算的結果
int vis[4000010];
struct node
{
    int now[10];
    int x;
    int bs;
} ks,mb,p;
queue<node> Q;
int cantor(int *s)
{
    int i,j,num=0,temp;
    for(i=0; i<9; i++)
    {
        temp=0;//temp記錄當前數位前面的低數位中小於當前位數上的數字的個數
        for(j=i+1; j<9; j++)
            if(s[j]<s[i])
                temp++;
        num+=jc[9-1-i]*temp;//乘以相應的階乘
    }
    return num;
}
void bfs()
{
    int t,g=cantor(mb.now);
    Q.push(ks);
    vis[cantor(ks.now)]=1;
    while(!Q.empty())
    {
        p=Q.front();
        if(cantor(p.now)==g)
        {
            printf("%d\n",p.bs);
            return;
        }
        int x=p.x/3,y=p.x%3;
        for(int i=0; i<4; i++)
        {
            int x0=x+fx[i][0];
            int y0=y+fx[i][1];
            if (x0<0||x0>2||y0<0||y0>2)
                continue;
            node q=p;
            q.x=x0*3+y0;
            q.bs++;
            q.now[p.x]=q.now[q.x];
            q.now[q.x]=0;
            t=cantor(q.now);
            if(!vis[t])
            {
                vis[t]=1;
                Q.push(q);
            }
        }
        Q.pop();
    }
    printf("-1\n");
}

                                                         兩點

福克斯在玩一款手機解迷遊戲,這個遊戲叫做"兩點"。基礎級別的時候是在一個 n×mn×m 單元上玩的。像這樣:

每一個單元有包含一個有色點。我們將用不同的大寫字母來表示不同的顏色。

這個遊戲的關鍵是要找出一個包含同一顏色的環。看上圖中 44 個藍點,形成了一個環。一般的,我們將一個序列 d1,d2,...,dkd1,d2,...,dk 看成一個環,當且僅當它符合下列條件時:

1. 這 kk 個點不一樣,即當 i≠ji≠j 時,didi 和 djdj 不同。

2. kk 至少是 44。

3. 所有的點是同一種顏色。

4. 對於所有的 1≤i≤k−11≤i≤k−1: didi 和 di+1di+1 是相鄰的。還有 dkdk 和 d1d1 也應該相鄰。單元 xx 和單元 yy 是相鄰的當且僅當他們有公共邊。

當給出一幅格點時,請確定裏面是否有環。

Input

單組測試數據。

第一行包含兩個整數 nn 和 mm (2≤n,m≤50)(2≤n,m≤50): 板子的行和列。

接下來 nn 行,每行包含一個有 mm 個字母的串,表示當前行每一個點的顏色。每一個字母都是大寫字母。

Output

如果有環輸出 Yes,否則輸出 No。

Example

input

Copy

3 4
AAAA
ABCA
AADA

output

Copy

No
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
char mp[60][60];
int vis[60][60],fg,n, m;
int fx[] = {0, -1, 0, 1};
int fy[] = {1, 0, -1, 0};

void dfx(int x, int y, char c, int dir)
{
    if(x < 0 || x > n-1 || y < 0 || y > m-1 || mp[x][y] != c)
        return;
    if(vis[x][y])
    {
        fg = 1;
        return;
    }
    vis[x][y] = 1;
    for(int i = 0; i < 4; i++)
    {
        if(dir == 0 && i == 2)
            continue;
        if(dir == 1 && i == 3)
            continue;
        if(dir == 2 && i == 0)
            continue;
        if(dir == 3 && i == 1)
            continue;
        int xx = x + fx[i];
        int yy = y + fy[i];
        dfx(xx, yy, c, i);
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++)
        scanf("%s", mp[i]);
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(fg)
                break;
            if(vis[i][j])
                continue;
            dfx(i, j, mp[i][j], -1);
        }
        if(fg)
            break;
    }
    if(fg)
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

                                                    大臣的旅費

很久以前,T 王國空前繁榮。爲了更好地管理國家,王國修建了大量的快速路,用於連接首都和王國內的各大城市。

爲節省經費,T 國的大臣們經過思考,制定了一套優秀的修建方案,使得任何一個大城市都能從首都直接或者通過其他大城市間接到達。同時,如果不重複經過大城市,從首都到達每個大城市的方案都是唯一的。

J 是 T 國重要大臣,他巡查於各大城市之間,體察民情。所以,從一個城市馬不停蹄地到另一個城市成了 J 最常做的事情。他有一個錢袋,用於存放往來城市間的路費。

聰明的 J 發現,如果不在某個城市停下來修整,在連續行進過程中,他所花的路費與他已走過的距離有關,在走第 xx 千米到第 x+1x+1 千米這一千米中(xx 是整數),他花費的路費是 x+10x+10 這麼多。也就是說走 11 千米花費 1111,走 22 千米要花費 2323。

J 大臣想知道:他從某一個城市出發,中間不休息,到達另一個城市,所有可能花費的路費中最多是多少呢?

Input

輸入的第一行包含一個整數 nn (0<n<20)(0<n<20),表示包括首都在內的 T 王國的城市數

城市從 1 開始依次編號,1 號城市爲首都

接下來 n−1n−1 行,描述 T 國的高速路(T 國的高速路一定是 n−1n−1 條)

每行三個整數 Pi,Qi,DiPi,Qi,Di,表示城市 PiPi 和城市 QiQi 之間有一條高速路,長度爲 DiDi 千米 (0<Di<100)(0<Di<100)

Output

輸出一個整數,表示大臣 J 最多花費的路費是多少

Example

input

Copy

5
1 2 2
1 3 1
2 4 5
2 5 4

output

Copy

135
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int mp[30][30],n,P,Q,D,sum;
int main()
{
    cin>>n;
    int ls=n-1;
    memset(mp,inf,sizeof(mp));
    while(ls--)
    {
        cin>>P>>Q>>D;
        mp[P][Q]=mp[Q][P]=D;
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(mp[i][k]!=inf&&mp[k][j]!=inf)
                    mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
            }
        }
    }
    for(int i=1; i<=n; i++)
        for(int j=i+1; j<=n; j++)
            sum=max(sum,mp[i][j]);
    cout<<sum*(sum+1)/2+sum*10<<endl;
    return 0;
}

                                                     Tri Tiling

In how many ways can you tile a 3×n3×n rectangle with 2×12×1 dominoes? Here is a sample tiling of a 3×123×12 rectangle.

Input

Input consists of several test cases followed by a line containing −1−1. Each test case is a line containing an integer 0≤n≤300≤n≤30.

Output

For each test case, output one integer number giving the number of possible tilings.

Example

input

Copy

0
6
10
-1

output

Copy

1
41
571
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int dp[50],n;
int main()
{
    dp[0]=1;
    dp[2]=3;
    for(int i=4; i<=30; i++)
        dp[i]=4*dp[i-2]-dp[i-4];
    while(cin>>n&&n!=-1)
    {
        cout<<dp[n]<<endl;
    }
    return 0;
}

                                                01 組成的 N 的倍數

output

standard output

給定一個自然數 N,找出一個 M,使得M>0 且 M 是 N 的倍數,並且 M 的 10 進製表示只包含 0 或 1,求最小的 M。

Input

輸入 1個數 N。(1≤N≤106)(1≤N≤106)

Output

輸出符合條件的最小的 M。

Examples

input

Copy

1

output

Copy

1

input

Copy

4

output

Copy

100
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
struct node
{
    int x;
    int q;
} p[5000010];
int vis[5000010],n,ct;//vis餘數狀態0未出現,1出現
void dfs(int y)
{
    int ans=p[y].q;
    if(ans<=0)
    {
        cout<<1;
        return;
    }
    dfs(ans);
    cout<<p[ans].x;
    return;
}
void bfs()
{
    ct=1;
    memset(vis,0,sizeof(vis));
    node ls1,ls2;
    ls1.x=1,ls1.q=0;
    queue<node> qu;
    p[0].x=1;
    p[0].q=0;
    qu.push(ls1);
    while(!qu.empty())
    {
        ls2=qu.front();
        qu.pop();
        for(int i=0; i<=1; i++)
        {
            ls1.x=ls2.x*10+i;
            ls1.x%=n;//餘數
            if(!vis[ls1.x])
            {
                ls1.q=ct;
                vis[ls1.x]=1;
                p[ct].x=i;
                p[ct].q=ls2.q;
                qu.push(ls1);
                if(ls1.x==0)
                {
                    dfs(ct);
                    cout<<i<<endl;
                    return;
                }
                ct++;
            }
        }
    }
}
int main()
{
    cin>>n;
    if(n==1)
        cout<<1<<endl;
    else
        bfs();
    return 0;
}

                                                         剪格子

如下圖所示,3×33×3 的格子中填寫了一些整數。

我們沿着圖中的星號線剪開,得到兩個部分,每個部分的數字和都是 6060。

本題的要求就是請你編程判定:對給定的 m×nm×n 的格子中的整數,是否可以分割爲兩個部分,使得這兩個區域的數字和相等。

如果存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。

如果無法分割,則輸出 00。

Input

程序先讀入兩個整數 m,nm,n 用空格分割 (m,n<10)(m,n<10),表示表格的寬度和高度。

接下來是 mm 行,每行 nn 個正整數,用空格分開。每個整數不大於 1000010000。

Output

輸出一個整數,表示在所有解中,包含左上角的分割區可能包含的最小的格子數目。

Example

input

Copy

3 3
10 1 52
20 30 1
1 2 3

output

Copy

3

題解:

題目大體意思是要分成兩部分,這兩部分數字的和要相等。

背後的意思是 怎麼分成兩部分。

正常思路是 dfs 上下左右,左上角所在集合標記成 1,一旦標記集合的和是總和的一半,此時實現了 “分開”。在每次“分開”中更新最小的塊數。

問題來了。(假設陰影處是最優解)

所以 考慮添加方向

變成 8 個方向

int dir[8][2] = {1, 0, 1, -1, 0, 1, 0, -1, -1, 0, -1, 1, 1, 1, -1, -1};

上下左右,左上 左下 右上 右下

但是會有很多組數據超時

最後考慮,斜着的方向只添加一個,左下(從 0, 0 處劃分兩塊,大體方向是左下,下,右下)

int dx[] = {0, 0, 1, -1, 1};
int dy[] = {1, -1, 0, 0, -1};

又出現新問題了

左下角的沒有辦法剪,所以說:

雖然這種情況可以搜索到,但是這種情況不是解。

怎麼排除這種情況呢

被標記的小塊的,看看周圍有沒有提前被標記了的就行了。(上下左右是否接壤)

左下角的上面和右面都沒有接壤,所以沒有辦法剪下來,所以排除。

大體思路就是這樣

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n, m;
int ans = INF;
int e[20][20];
int sum; //總和
int dx[] = {0, 0, 1, -1, 1};
int dy[] = {1, -1, 0, 0, -1};
bool vis[20][20];
bool check() { // 檢查有沒有斜着蹦出來的
    int flag = 0;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++) {
            if (vis[i][j]) { // 看看所有被標記點 是不是有斜着的
                flag = 1;
                int k = 0;
                for (k = 0; k < 4; k++) {
                    if (i + dx[k] < 0 || i + dx[k] >= m || j + dy[k] < 0 ||
                        j + dy[k] >= n)
                        continue; // 界外
                    if (vis[i + dx[k]]
                           [j + dy[k]]) { //   試探: i+dx[k]  j+dy[k]
                                          //   (上下左右被標記 ) 就跳出
                        flag = 0;
                        break; //說明它的上下左右至少有一個接壤的
                               //也就是說不能出現斜着蹦出來的
                    }
                }
                if (flag)
                    return false;
            }
        }
    return true;
}
void dfs(int x, int y, int res, int step) { // x,y 標記的和,標記了多少塊
    if (res > sum / 2)
        return;
    if (res == sum / 2 && check()) {
        ans = min(ans, step);
        return;
    }
    for (int i = 0; i <= 4; i++) {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if (xx >= m || yy >= n || xx < 0 || yy < 0)
            continue; // 界外
        if (!vis[xx][yy]) {
            vis[xx][yy] = 1;
            dfs(xx, yy, res + e[xx][yy], step + 1);
            vis[xx][yy] = 0;
        }
    }
}
int main() {
    scanf("%d%d", &m, &n);
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            scanf("%d", &e[i][j]), sum += e[i][j];
    if (sum & 1) {
        printf("0\n");
        return 0;
    }
    vis[0][0] = 1;
    dfs(0, 0, e[0][0], 1);
    if (ans == INF)
        printf("0\n");
    else
        printf("%d\n", ans);
    return 0;
}

 

發佈了805 篇原創文章 · 獲贊 42 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章