当前位置:C++技术网 > 资讯 > 有关于抽签并表达抽签的组合的题目

有关于抽签并表达抽签的组合的题目

更新时间:2017-03-11 15:58:44浏览次数:1+次

以下是我的思路:

我先把主函数看了两遍,但没有真正理解到主函数中函数声明所包含四个字母的真正含义,我的理解仅仅是为函数定义的计算提供值。然后将值带入到函数定义中,第一步将if排除了,第二步没有看懂两个循环的意思。


题目:

CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)


#include <stdio.h>
#define N 6
#define M 5
#define BUF 1024

void f(int a[], int k, int m, char b[])
{
    int i,j;
    
    if(k==N){
        b[M] = 0;
        if(m==0) printf("%s\n",b);
        return;
    }
    
    for(i=0; i<=a[k]; i++){
        for(j=0; j<i; j++) b[M-m+j] = k+''''A'''';
        ______________________;  //填空位置
    }
}
int main()
{    
    int  a[N] = {4,2,2,1,1,3};
    char b[BUF];
    f(a,0,M,b);
    return 0;
}

仔细阅读代码,填写划线部分缺少的内容。

注意:不要填写任何已有内容或说明性文字。


C++技术网会员解答:

    你好,感谢对C++技术网的支持与信任。

    对于算法类的提问,我们要做一些说明。算法类的刷题题目,一般是需要大量刷题训练的,需要具备常用的数学逻辑思维和解题经验。如果你一开始对这类题目无从下手,最好的方法就是看别人如何解题的。按照别人的思路,一步步先走通,你全部可以理解了,这是第一步。刷题竞赛之类的并不需要你真的完全自己创造出来的解题思路,基本都是把各种解题思路混在一起考。当积累了大量的经验之后,你大脑里形成了一套基本的解题思路库,对于一般的题目也是可以得心应手。而对于复杂的题目,也可以从这些基础的解题思路里组合得到。

    一般的竞赛题这样就可以应付了。如果题目出的太高深,需要奇妙的解题思路才行,那就要靠全新的解题方法,那是真正牛逼的人能够搞定的。这样需要深厚扎实的数学功底和强悍的数学逻辑思维,这类人一般都是我们所谓的天才!

    我们一般人都是大量积累经验,从别人的经验里汲取思路学习。然后多尝试解决不同类型的算法题,来发散自己的思维。对于自己思维的弱点,比如逆向思维,你觉得很难,那就要加强练习,针对性训练。

    我们的解答无法代替你解题,我们也不能帮你解题,我们可以帮助你学习解题方法,告诉你如何学习,你就可以更高效的去做这件事,而不是面对这样的题目不知所措。

    下面的题目做一个简单的分析演示,并不是解题过程,供你参考,促进你学习:

#include <stdio.h>
#define N 6  //被抽的签数
#define M 5  //最后一个签的位置
#define BUF 1024 //缓存数组的大小

void f(int a[], int k, int m, char b[])
{
    //a签池 k签池数组下标索引,m最后一个签的位置,存放抽签结果的数组(通过大概分析main和f函

数的if得到的解释)
    int i,j;
    
    if(k==N){//下标和签数相同,抽到了最后一个,表示抽完了,可以打印结果
        b[M] = 0;//设置字符数组结尾,形成字符串
        if(m==0) printf("%s\n",b);//如果要打印出来,m必须为0.一开始是前后一个签的位置,表明m

必须递减
        return;
    }
    
    for(i=0; i<=a[k]; i++){//第一次等价for(i=0; i<=4; i++)
        for(j=0; j<i; j++) b[M-m+j] = k+''''A'''';//第一次b[0]=''''A'''',b[0]=''''A'''' b[1]=''''A'''', b[0]=''''A'''' b[1]=''''A'''' b[2]=''''A'''',b[0]=''''A'''' b[1]=''''A'''' b[2]=''''A'''' b[3]=''''A''''
        ______________________;  //填空位置
    }
}
int main()
{    
    int  a[N] = {4,2,2,1,1,3};
    char b[BUF];
    f(a,0,M,b);
    return 0;
}
     我们还是从代码的执行顺序来阅读代码。

0.完全弄清楚题目的意思(有些题目并不会表述的很清楚,有些条件也是默认的,这也是刷题得到的经验,叫做揣测出题老师的意图,其实挺蛋疼的。题目不能完全表述清楚,还要揣测出题意图。题目应该充分说明,让做题的人完全理解。)

1.首先阅读预定义的常量,但是这里并不能看到意义。这个需要我们在代码里来确定。

2.阅读main函数,确定整体思路。我们这里a数组,b数组,f函数。三个关键点。这里可以确定N和BUF是数组大小。M的含义不明确,需要到f函数确定。a、b、M的含义都需要在f函数里确定。

3.分析关键函数f通过分析if这段代码,我们应该可以发现,我们的结果是要printf打印出来。当然,这里只能确定题目是使用printf来输出结果,而不是写到文件。但是是否一定在if这里输出结果呢?不一定,因为后面填空的位置是一个未知。当然,前面一开始我们都说过,刷题是要有经验的。如果你觉得填空的位置可以写printf,说明你没有经验了。一般填空的地方是算法的关键语句,像printf这样的构不成关键语句。当然,我们不要依靠经验来分析题目,而是要走纯粹的逻辑分析。

    我们反向来推理,如果我们在填空的位置填入printf,那就意味着,输出的结果集中在填空的位置,如果这样的话,无法形成核心的逻辑代码了。这里只有一句代码。根据f函数传入的参数,if里的参数导致printf执行不了。执行不了的代码对题目是多余的,根据经验,一般这样的做法在题目是不存在的。算法题的代码里,基本上都是没有多余的。当然,这也是要靠经验的。

    不过我们还是不以经验来做题。我们结合题目的意思,不管在填空的位置如何打印,都得不到需要的结果。因为双循环的外循环已经定型了,只有4次。题目的结果有101行,充分说明printf不是在填空位置填的。当然,题目不会变态到让你在一行代码里既写循环又写printf。当然,这还是经验。当然,出题老师变不变态你还是不知道,万一是呢?

    我们继续进行逻辑分析,不按照经验来。我们将双循环的参数进行迭代,得到上面代码注释里看到的一组结果。然后你再看看在填空中如何写一行代码可以将结果拼出来。记得,要加循环,增加结果数量。要printf才能打印,要进行结果处理,才能得到题目要求的结果,还有,只有一行代码。你想的出来吗?

    基本上到这里,在填空位置,上述方案基本可以放弃。反正我是想不出来的。我们这个题目不是世界级的难题,所以不用再这里死啃。按照经验,一般关键的填空位置填对了答案,可以让你产生一种“哎呀,原来如此”的感觉!答案一般填写的不会太复杂,但是很巧妙。这些经验都是可以加速你解题的。不过,没有经验,完全靠逻辑也是只是辛苦点。

    那么以上推理,填空不会有printf。既然如此,结果一定要printf的,而if里一次执行又不能printf,而且就算执行一次又有什么卵用,题目需要101个打印。f函数没有循环来执行printf,那么还有什么办法可以让printf玩转起来呢?答案就是。让f函数不停的执行起来。而f函数在main只被执行一次,我们所有的希望也都集中在了填空的位置。

    答案就是,我们要在填空的位置填写f函数的调用。这样是什么意思呢?递归!

    到此,是不是一下恍然大悟了。前面的疑问都可以解开了。f递归调用,可以打印很多printf,而且if这里的代码就不是摆设了,而且也是一个递归终结条件。很合理。然后101个结果也可以通过递归得到了。而填空的位置代码量不会很多,一个f函数调用可以实现这么多好处,也让题目不变态(经验),递归作为考点(经验),一切都合理了。从而我们可以确定,填空的位置一定是f函数调用。

    那么,如何调用传参呢?这才是真正的考点。我想能走到这一步,可以卡死很多人了。

    我们分析if的代码,如果printf要打印结果,那么m必须为0。而我们传入的m开始大于0.这就意味着,我们需要对m做递减。而打印只有一次,我们就需要事先在双循环里将结果处理好。双循环形成一部分结果,填空的位置的递归调用来对结果进行递归打印处理或对结果进行加工。

    到这里就需要清楚题目的要求,要得到什么结果。而题目的意思如果没有表述清楚,那么就只能靠经验理解题目的意思了。然互再配合代码的逻辑来得到结果。

    我们并不提供结果的解题。我们通过这个分析过程,进行严密的逻辑分析,帮助你理解解题方法和思路。因为题目的参数很多,很容易让你搞不清楚各个参数的意义,请一定记得写好注释。把你的推理思路先注释上,有助于你往后面分析。