dfs进阶

  当自己以为自己深搜(其实就是暴力啦)小成的时候,发现没有题目的积累还是很难写出程序,自己真的是太年轻了;总结一下就是做此类题看是否需要使用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个格子就代表答案出来了,具体看程序:

 #include<stdio.h>
int a[][];
int re1(int row,int col,int num)//行列是否重复
{
int i;
for(i=;i<=;i++)
if(a[row][i]==num||a[i][col]==num)
return ;
return ;
}
int re2(int row,int col,int num)//小九宫格是否重复
{
int i,j,x,y;
x=(row-)/*+;
y=(col-)/*+;
for(i=x;i<x+;i++)
for(j=y;j<y+;j++)
if(a[i][j]==num)
return ;
return ;
}
void dfs(int row,int col)
{
int i,j;
if(row>)
{
for(i=;i<=;i++)
{
for(j=;j<=;j++)
printf("%d",a[i][j]);
printf("\n");
}
exit();
}
if(!a[row][col])
{
for(i=;i<=;i++)
{
if(!re1(row,col,i)&&!re2(row,col,i))
{
a[row][col]=i;
dfs(row+(col+)/,(col+)%);//下一个格子
}
}
a[row][col]=;
}
else
{
dfs(row+(col+)/,(col+)%);
}
}
int main()
{
int i,j;
char s[];
for(i=;i<=;i++)
{
scanf("%s",s+);
for(j=;j<=;j++)
a[i][j]=s[j]-'';
}
dfs(,);
return ;
}

 ---------分割线---------

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)就是一个分解方法了,具体看代码吧:

 #include<stdio.h>
int a[];
int n;
void dfs(int cur,int t)
{
int i,x,y;
if(cur==n)
{
x=;y=;
for(i=;i<n;i++)
x*=a[i];
for(i=;i<n;i++)
y+=x/a[i];
if(x==y)
{
for(i=;i<n;i++)
printf("1/%d ",a[i]);
printf("\n");
}
return;
}
else for(i=t;i<;i++)
{
a[cur]=i;
dfs(cur+,i+);
}
}
int main()
{
scanf("%d",&n);
dfs(,);
return ;
}
上一篇:浅析LRC歌词文件


下一篇:[20181109]12c sqlplus rowprefetch参数5