• 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个格子就代表答案出来了,具体看程序:

     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 }
  • 相关阅读:
    Navigator对象关于语言的属性
    对ng-repeat的表格内容添加不同样式:ng-style
    ng-repeat
    ES 6 : 函数的扩展
    二维码下载,区分是 ios 和 android
    gulp配置备份
    [转]移动端web页面使用字体的思考
    移动开发总结
    前端优化:雅虎35条
    input填写银行卡号,每四位空一隔
  • 原文地址:https://www.cnblogs.com/search-the-universe/p/last_month_2.html
Copyright © 2020-2023  润新知