枚举,很暴力!

坑爹的奥数

将数字 1~9 分别填入9个方框中,每个数字只能使用一次使等式成立。□□□+□□□=□□□!

  • 更好的实现方法:标记法!
    用一个 book 数组来解决互不相等的问题。
#include <stdio.h>
int main(){
    int a[10], i, total = 0;
    int book[10], sum;
    //这里可以用 a[1]~a[9] 来代替刚才的 a,b,c,d,e,f,g,h,i
    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 (i = 1; i <= 9;i++)
                                        //初始化 book 数组
                                            book[i] = 0;
                                        for (i = 1; i <= 9;i++)
                                        //如果某个值出现过就标记一次
                                            book[a[i]] = 1;
                                        sum = 0;
                                        //统计共出现了多少个不同的数
                                        for (i = 1;i <= 9;i++)
                                            sum += book[i];
                                        //如果正好出现了9个不同的数,并且满足等式条件,则输出
                                        if(sum==9&&a[i]*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);
    getchar();
    getchar();
    return 0;
}
  • DFS
#include <stdio.h>
int a[10], book[10], total = 0;
void dfs(int step){
    int i;
    if(step==10){
        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 <= 9;i++){
        if(book[i]==0){
            a[step] = i;
            book[i] = 1;
            dfs(step + 1);
            book[i] = 0;
        }
    }
    return;
}
int main(){
    dfs(1);
    printf("total=%d", total / 2);
    getchar();
    getchar();
    return 0;
}

炸弹人的策略

  • 墙用 # 表示
  • 敌人用 G 表示
  • 空地用 . 表示
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G###.#G#
##G...g.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
  • 首先,需要一个二维字符数组来存储这个地图,至于将炸弹放置到哪一个点可以消灭的敌人最多,则需要一个个地来尝试。炸弹的爆炸方向是沿上下左右四个方向,因此我们在对每一个点进行枚举的时候,需要沿着上下左右四个方向分别统计可以消灭敌人的数目。最终输出可以消灭敌人最多的那个点。请注意这里是从0行0列开始时算的。
  • 如何分别统计上下左右四个方向上可以消灭的敌人数量呢?
  • 只要搞清楚一个方向,其他的方向都是一样的,这里就以向下统计为例。
  • 向下就是 y 不变,x 每次增加 1,直到遇到墙为止。
#include <stdio.h>
int main(){
    char a[20][21];
    int i, j;
    int sum, map = 0, p, q, x, y, n, m;
    //读入 n和 m表示有多少行字符,m表示每行有多少列
    scanf("%d %d", &n, &m);
    for (i = 0; i <= n - 1;i++)
        scanf("%s", a[i]);
    //用两重循环枚举地图中的每一个点
    for (i = 0; i <= n - 1;i++){
        for (j = 0; j <= m - 1;j++){
            //首先判断这个点是不是平地,是平地才能被放置炸弹
            if(a[i][j]=='.'){
                sum = 0;
                //sum 用来计数(可以消灭的敌人数),所以需要初始化为 0
                x = i;
                //将坐标 i,j 复制到两个新变量 x,y中,以便向上下左右四个方向分别统计可以消灭的敌人数
                //向上统计可以消灭的敌人数
                y = j;
                while(a[x][y]=='G'){
                //判断是不是墙,如果不是墙就继续 
                    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++;
                    //继续向右统计
                }
                //更新 map的值
                if(sum>map){
                //如果当前点所能消灭的敌人总数大于 map,则更新 map
                    map = sum;
                    //并用 p和 q记录当前点的坐标
                    p = i;
                    q = j;
                }
            }
        }
    }
    printf("将炸弹放置在(%d,%d),最多可以消灭%d个敌人\n", p, q, map);
    getchar();
    getchar();
    return 0;
}

火柴棍等式

  • 注意
  • 加号与等式各自需要两根火柴棍
  • 如果 A!=B,则 A+B=C 与 B+A=C 视为不同的等式(A,B,C都大于0)
  • 所有根火柴棍必须全部用上

思路

  • 暴力枚举
    将枚举C改成通过 A+B 来算出 C,就将原来需要运行1000多秒的程序降低到了1秒。
#include <stdio.h>

int fun(int x){
    int num;
    int f[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
    //用一个数组来记录 0~9每个数字需要用多少根火柴棍
    while(x/10!=0){
    //如果 x/10的商不等于 0的话,说明这个数至少有两位
        num += f[x % 10];
        //获得 x的末尾数字并将此数所需要的火柴棍累加到 num中
        x /= 10;
        //去掉 x的末尾数字,例如 x的值为 123,则现在 x的值为 12
    }
    num += f[x];
    return num;
}

int main(){
    int a, b, c, m, i, sum = 0;
    scanf("%d", &m);
    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个不同的等式", sum);
    getchar();
    getchar();
    return 0;
}

数的全排列

案例:
123 的全排列
三重循环嵌套

#include <stdio.h>
int main(){
    int a, b, c;
    for (a = 1; a <= 3;a++){
        for (b = 1; b <= 3;b++){
            for (c = 1; c <= 3;c++){
                if(a!=b&&a!=c&&b!=c)
                    printf("%d%d%d\n", a, b, c);
            }
        }
    }
    return 0;
}

万能的搜索…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值