奥数问题
+ = \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>=0)
3. 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;
}