坑爹的奥数
将数字 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;
}
万能的搜索…