当自己以为自己深搜(其实就是暴力啦)小成的时候,发现没有题目的积累还是很难写出程序,自己真的是太年轻了;总结一下就是做此类题看是否需要使用vis数组优化以及继续搜索的条件或者满足答案的条件。以下为2题比较经典的题目:
1、数独
你一定听说过“数独”游戏。
玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。
数独的答案都是唯一的,所以,多个解也称为无解。
本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。
本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。
格式要求,输入9行,每行9个数字,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。
例如:
输入:
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764
再例如,输入:
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400
程序应该输出:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452
---------分割线---------
总结一下题意,在9个3*3的九宫格里填上1~9的数字(不能重复),且9*9的大九宫格每行每列的数字都不能重复。程序总结一下就是81个格子一个一个1~9试着填,中间条件判断是否满足,填完81个格子就代表答案出来了,具体看程序:
1 #include<stdio.h> 2 int a[10][10]; 3 int re1(int row,int col,int num)//行列是否重复 4 { 5 int i; 6 for(i=1;i<=9;i++) 7 if(a[row][i]==num||a[i][col]==num) 8 return 1; 9 return 0; 10 } 11 int re2(int row,int col,int num)//小九宫格是否重复 12 { 13 int i,j,x,y; 14 x=(row-1)/3*3+1; 15 y=(col-1)/3*3+1; 16 for(i=x;i<x+3;i++) 17 for(j=y;j<y+3;j++) 18 if(a[i][j]==num) 19 return 1; 20 return 0; 21 } 22 void dfs(int row,int col) 23 { 24 int i,j; 25 if(row>9) 26 { 27 for(i=1;i<=9;i++) 28 { 29 for(j=1;j<=9;j++) 30 printf("%d",a[i][j]); 31 printf(" "); 32 } 33 exit(0); 34 } 35 if(!a[row][col]) 36 { 37 for(i=1;i<=9;i++) 38 { 39 if(!re1(row,col,i)&&!re2(row,col,i)) 40 { 41 a[row][col]=i; 42 dfs(row+(col+1)/10,(col+1)%10);//下一个格子 43 } 44 } 45 a[row][col]=0; 46 } 47 else 48 { 49 dfs(row+(col+1)/10,(col+1)%10); 50 } 51 } 52 int main() 53 { 54 int i,j; 55 char s[11]; 56 for(i=1;i<=9;i++) 57 { 58 scanf("%s",s+1); 59 for(j=1;j<=9;j++) 60 a[i][j]=s[j]-'0'; 61 } 62 dfs(1,1); 63 return 0; 64 }
---------分割线---------
2、单位分数
1/a 的分数称为单位分数。
可以把1分解为若干个互不相同的单位分数之和。
例如:
1 = 1/2 + 1/3 + 1/9 + 1/18
1 = 1/2 + 1/3 + 1/10 + 1/15
1 = 1/3 + 1/5 + 1/7 + 1/9 + 1/11 + 1/15 + 1/35 + 1/45 + 1/231
等等,类似这样的分解无穷无尽。
我们增加一个约束条件:最大的分母必须不超过30
请你求出分解为n项时的所有不同分解法。
数据格式要求:
输入一个整数n,表示要分解为n项(n<12)
输出分解后的单位分数项,中间用一个空格分开。
每种分解法占用一行,行间的顺序按照分母从小到大排序。
例如,
输入:
4
程序应该输出:
1/2 1/3 1/8 1/24
1/2 1/3 1/9 1/18
1/2 1/3 1/10 1/15
1/2 1/4 1/5 1/20
1/2 1/4 1/6 1/12
再例如,
输入:
5
程序应该输出:
1/2 1/3 1/12 1/21 1/28
1/2 1/4 1/6 1/21 1/28
1/2 1/4 1/7 1/14 1/28
1/2 1/4 1/8 1/12 1/24
1/2 1/4 1/9 1/12 1/18
1/2 1/4 1/10 1/12 1/15
1/2 1/5 1/6 1/12 1/20
1/3 1/4 1/5 1/6 1/20
---------分割线---------
这题就比较简单啦,连vis数组都不用了,不过题目给的答案和题意不太符合,题意是不超过30,但答案不包括30这个数字。答案不包括30就不包括吧,从第一项2~29开始填,从上一项填的数字到29填当前项,填到第n项且满足条件(通分后相加判断分子分母是否相等,即和是否为1)就是一个分解方法了,具体看代码吧:
1 #include<stdio.h> 2 int a[13]; 3 int n; 4 void dfs(int cur,int t) 5 { 6 int i,x,y; 7 if(cur==n) 8 { 9 x=1;y=0; 10 for(i=0;i<n;i++) 11 x*=a[i]; 12 for(i=0;i<n;i++) 13 y+=x/a[i]; 14 if(x==y) 15 { 16 for(i=0;i<n;i++) 17 printf("1/%d ",a[i]); 18 printf(" "); 19 } 20 return; 21 } 22 else for(i=t;i<30;i++) 23 { 24 a[cur]=i; 25 dfs(cur+1,i+1); 26 } 27 } 28 int main() 29 { 30 scanf("%d",&n); 31 dfs(0,2); 32 return 0; 33 }