暴力枚举法

奥数问题


+ = \boxed{}\boxed{}\boxed{} + \boxed{}\boxed{}\boxed{}=\boxed{}\boxed{}\boxed{} +=

将数字分别填入,每个数组只能使用一次是使得等式成立,问一共有多少总组合呢?

方法一:暴力枚举

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

int main()
{
    int total=0;
    int a,b,c,d,e,f,g,h,i;
    for(a = 1; a <= 9; a++)
    for(b = 1; b <= 9; b++)
    for(c = 1; c <= 9; c++)
    for(d = 1; d <= 9; d++)
    for(e = 1; e <= 9; e++)
    for(f = 1; f <= 9; f++)
    for(g = 1; g <= 9; g++)
    for(h = 1; h <= 9; h++)
    for(i = 1; i <= 9; i++)
    {
        if(a!=b && a!=c && a!=d && a!=e && a!=f && a!=g && a!=h && a!=i
        &&         b!=c && b!=d && b!=e && b!=f && b!=g && b!=h && b!=i
        &&                 c!=d && c!=e && c!=f && c!=g && c!=h && c!=i
        &&                         d!=e && d!=f && d!=g && d!=h && d!=i
        &&                                 e!=f && e!=g && e!=h && e!=i
        &&                                         f!=g && f!=h && f!=i
        &&                                                 g!=h && g!=i
        &&                                                         h!=i
        && a*100 + b*10 + c + d*100 + e*10 + f == g*100 + h*10 + i)
        {
            total++;
            printf("%d%d%d+%d%d%d=%d%d%d\n", a,b,c,d,e,f,g,h,i);
        }
    }
    printf("total=%d",total/2);
    return 0;
}

一共是168组组合

方法二:用book标记,进行枚举

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

int main()
{
    int total=0;
    int book[10]={0};
    int a[10];
    for(a[1] = 1; a[1] <= 9; a[1]++)
    for(a[2] = 1; a[2] <= 9; a[2]++)
    for(a[3] = 1; a[3] <= 9; a[3]++)
    for(a[4] = 1; a[4] <= 9; a[4]++)
    for(a[5] = 1; a[5] <= 9; a[5]++)
    for(a[6] = 1; a[6] <= 9; a[6]++)
    for(a[7] = 1; a[7] <= 9; a[7]++)
    for(a[8] = 1; a[8] <= 9; a[8]++)
    for(a[9] = 1; a[9] <= 9; a[9]++)
    {
        for(int i = 1; i <= 9; i++)
            book[i] = 0;
        for(int i = 1; i <= 9; i++)
        {
            book[a[i]] = 1;
        }
        int sum = 0;
        for(int i = 1; i <= 9; i++)
        {
            if(book[i] == 1)
                sum++;
        }
        
        if(sum == 9 && a[1]*100 + a[2]*10 + a[3] + a[4]*100 + a[5]*10 + a[6] == a[7]*100 + a[8]*10 + a[9])
        {
            total++;
            printf("%d%d%d+%d%d%d=%d%d%d\n", a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
        }
    }
    printf("total=%d",total/2);
    return 0;
}

方法三:用深度优先搜索

#include <bits/stdc++.h>
using namespace std;
int a[10], book[10], n;
int total = 0;
void dfs(int step)
{
    // printf("dfs in step %d\n",step);
    
    int i;
    if(step==n+1)
    {
        // // printf("sted is over, print\n");
        // for(int j = 1; j <= n; j++)
        //     printf("%d",a[j]);
        // printf("\n");
        if(a[1]*100 + a[2]*10 + a[3] + a[4]*100 + a[5]*10 + a[6] == a[7]*100 + a[8]*10 + a[9])
        {
            total++;
            printf("%d%d%d+%d%d%d=%d%d%d\n", a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
        }                
        return;
    }
    for(i = 1; i <= n; i++)
    {
        // printf("i is %d\n", i);
        if(book[i] == 0)
        {
            a[step] = i;
            book[i] = 1;
            // printf("into next dfs\n");
            dfs(step+1);
            // printf("out next dfs\n");
            book[i] = 0;
        }
    }
    return;
}

int main()
{
    scanf("%d", &n);
    dfs(1);
    printf("total=%d",total/2);
    return 0;
}

全排列

#include <bits/stdc++.h>
using namespace std;
int a[10], book[10], n;

void dfs(int step)
{
    // printf("dfs in step %d\n",step);
    
    int i;
    if(step==n+1)
    {
        // printf("sted is over, print\n");
        for(int j = 1; j <= n; j++)
            printf("%d",a[j]);
        printf("\n");
        return;
    }
    for(i = 1; i <= n; i++)
    {
        // printf("i is %d\n", i);
        if(book[i] == 0)
        {
            a[step] = i;
            book[i] = 1;
            // printf("into next dfs\n");
            dfs(step+1);
            // printf("out next dfs\n");
            book[i] = 0;
        }
    }
    return;
}

int main()
{
    scanf("%d", &n);
    dfs(1);
    return 0;
}

炸弹人

方法一:暴力枚举

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

int main()
{
    char a[20][20];
    int n,m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i <= n-1; i++)
        scanf("%s", a[i]);
    int map = 0;
    int p, q;
    for(int i = 0; i <= n-1; i++)
    {
        for(int j = 0; j <= m-1; j++)
        {
            if(a[i][j] == '.')
            {
                int sum = 0;
                // cout << i << " " << j <<endl;
                int x = i;
                int y = j;
                while(a[x][y] != '#')
                {
                    if(a[x][y] == 'G')
                        sum++;
                    x++;
                }
                x = i, y = j;
                while(a[x][y] != '#')
                {
                    if(a[x][y] == 'G')
                        sum++;
                    x--;
                }
                x = i, y = j;
                while(a[x][y] != '#')
                {
                    if(a[x][y] == 'G')
                        sum++;
                    y++;
                }                
                x = i, y = j;
                while(a[x][y] != '#')
                {
                    if(a[x][y] == 'G')
                        sum++;
                    y--;
                }
                if(sum > map)
                {
                    map = sum;
                    p = i;
                    q = j;
                }
            }
        }
    }

    printf("%d",map);
}

方法二:用广度优先搜索

#include <bits/stdc++.h>
using namespace std;
struct note
{
  int x;
  int y;
};
char a[20][20];
int getnum(int i, int j)
{
    int sum = 0;
    // cout << i << " " << j <<endl;
    int x = i;
    int y = j;    

    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        x++;
    }
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        x--;
    }
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        y++;
    }                
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        y--;
    }
    return sum;
}
int next[4][2]={
  {0,1},
  {1,0},
  {0,-1},
  {-1,0}
};
int main()
{
    struct note que[401];
    int head=1, tail=1;
    int book[20][20]={0};
    
    int n,m,startx,starty;
    scanf("%d%d%d%d", &n, &m, &startx, &starty);
    for(int i = 0; i <= n-1; i++)
        scanf("%s", a[i]);
    que[tail].x = startx;
    que[tail].y = starty;
    tail++;
    book[startx][starty]=1;
    int max=getnum(startx,starty);
    int mx=startx;
    int my=starty;
    while(head<tail)
    {
       for(int k = 0; k <= 3; k++)
       {
           int tx = que[head].x+next[k][0];
           int ty = que[head].y+next[k][1];
           
           if(tx<0 || tx > n-1 || ty<0 || ty > m-1)
                continue;
           
           if(a[tx][ty]=='.'&& book[tx][ty]==0)
           {
               book[tx][ty]=1;
               que[tail].x = tx;
               que[tail].y = ty;
               tail++;
               int sum = getnum(tx,ty);
               if(sum > max)
               {
                   max=sum;
                   mx=tx;
                   my=ty;
               }
           }
       }
       head++;
    }
    printf("%d",max);
}

方法三:用深度优先搜索

#include<bits/stdc++.h>
using namespace std;
char a[20][21];
int book[20][20];
int maxValue, mx, my, n, m;
int getnum(int i, int j)
{
    int sum = 0;
    // cout << i << " " << j <<endl;
    int x = i;
    int y = j;    

    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        x++;
    }
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        x--;
    }
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        y++;
    }                
    x = i, y = j;
    while(a[x][y] != '#')
    {
        if(a[x][y] == 'G')
            sum++;
        y--;
    }
    return sum;
}

void dfs(int x, int y)
{
    int next[4][2]={
      {0,1},
      {1,0},
      {0,-1},
      {-1,0}
    };
    int sum = getnum(x,y);
    if(sum > maxValue)
    {
        maxValue = sum;
        mx = x;
        my = y;
    }
    
    for(int k = 0; k <= 3; k++)
    {
        int tx=x+next[k][0];
        int ty=y+next[k][1];
        if(tx<0 || tx>n-1 || ty<0 || ty > m-1)
            continue;
        if(a[tx][ty]=='.'&& book[tx][ty]==0)
        {
            book[tx][ty]=1;
            dfs(tx,ty);
        }
    }
    return;
}

int main()
{
    int startx, starty;
    scanf("%d%d%d%d", &n, &m, &startx, &starty);
    for(int i = 0; i <= n-1; i++)
        scanf("%s",a[i]);
    book[startx][starty]=1;
    maxValue = getnum(startx, starty);
    mx = startx;
    my = starty;
    dfs(startx,starty);
    
    printf("%d", maxValue);
    return 0;
}

字符串

假设s由a个字母A和b个字母B组成,问s可能形成的“循环节长度”由多少中可能?

输入

2 4

输出

4

k的可能取值以及对应的字符串s(一个k可能对应多种不同的s,只举一个例子)

3:BBABBA
4:BBAABB
5:BBBAAB
6:AABBBB

思路:字符这题,我是按照先用深度搜索进行全排列,之后用KMP计算每一个排列的循环节长度,最后用统计排序的方法输出统计值大于0的,统计值,

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
char str[200000002];
int book[200000002];
char proStr[200000002];
int a,b;
int n;

char st[1000100];
int next[1001000];
void getnext(char st[],int m)
{
    int j = 0 ,k = -1;
    next[0] = -1;
    while (j < m)
    {
        if (k == -1 || st[j] == st[k] )
        {
            ++j;
            ++k;
            next[j] = k;
        }
        else 
        {
            k = next[k];
        }
        //printf("%d\n",next[j]);
    }
}


int abct[7]={0};
void dfs(int step)
{
    // printf("dfs in step %d\n",step);
    
    int i;

    if(step==n+1)
    {
        // for(int j = 1; j <= n; j++)
        //     printf("%c",proStr[j]);
        // printf("\n"); 
        
        
        int len = n;
        char st[n];
        for(int p = 0; p <= n; p++)
        {
            st[p] = proStr[p+1];
        }
        getnext(st,len);
        if(len == 1) 
            printf("1\n");  
        // printf("%d\n",len - next[len]);
        int temp = len - next[len];
        abct[temp]++;
        // a[len-next[len]]++;
//        ct[len - next[len]]++;
        
        return;
    }
    for(i = 1; i <= n; i++)
    {
        // printf("i is %d\n", i);
        if(book[i] == 0)
        {
            proStr[step] = str[i];
            book[i] = 1;
            // printf("into next dfs\n");
            dfs(step+1);
            // printf("out next dfs\n");
            book[i] = 0;
        }
    }
    return;
}

int main()
{
    scanf("%d%d",&a,&b);
    n = a+b;
    for(int i = 1; i <= a; i++)
    {
        str[i] = 'A';
    }
    for(int i = a+1; i <= a+b; i++)
        str[i] = 'B';
    
    dfs(1);
    
    for(int j = 1; j <= a+b; j++)
        printf("%c", str[j]);
    printf("\n");
    // int sum = 0;
    // for(int m = 0; m <= n+1; m++)
    // {
    //     if(ct[m] > 0)
    //     {
    //         sum++;
    //     }
    // }
    // printf("%d",sum);
    
    
    // while (cin >> st)
    // {
    //     int len = strlen(st);
    //     getnext(st,len);
    //     if(len == 1) 
    //         printf("1\n");  
    //     printf("%d\n",len - next[len]);
    // }
    for(int i = 0; i <= 7; i++)
    {
        if(abct[i])
            printf("%d ", i);
    }
        
    
    
    return 0;
}

火柴棒等式

给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:

注意:
1. 加号与等号各自需要两根火柴棍
2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C>=03. n根火柴棍必须全部用上
#include<bits/stdc++.h>
using namespace std;
int fun(int x)
{
    int num = 0;
    int f[10] = {6,2,5,5,4,5,6,3,7,6};
    while(x/10 != 0)
    {
        num += f[x%10];
        x = x/10;
    }
    num += f[x];
    return num;
}

int main()
{
    int m;
    scanf("%d", &m);
    
    int a,b,c;
    int sum = 0;
    for(a=0; a <= 1111;a++)
    {
        for(b=0; b <= 1111; b++)
        {
            c=a+b;
            if(fun(a)+fun(b)+fun(c)==m-4)
            {
                printf("%d+%d=%d\n",a,b,c); 
                sum++;
            }
        }
    }
    printf("一共可以拼出%d个不等\n",sum);
    return 0;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值