有一道解释程序的水题没给非计算机专业的同学讲明白orz,在这里再练一下。。

源代码完全没有缩进真是难以忍受。。

p.s.懂递归就不用看了#include <stdio.h>

int n = 0;
int rest[7][7];
void swap(int *a, int *b)
{
  int m;
  m = *a;
  *a = *b;
  *b = m;
}
void perm(int list[], int k, int m)
{
  int i;
  int j;
  if(k > m)
  {
      for (i=0; i<7; i++)//判断list是否可行,不行就返回,行就输出list
      {
          for (j=0; j<7; j++)
          {
              if (rest[i][j] == 0)
              return;
              if (rest[i][j] != list[i])//list存结果
              continue;
              if (rest[i][j] == list[i])
              break;
          }
      }
  n++;
printf("Solution: %d\n", n);
printf("赵 钱 孙 李 周 吴 陈\n");
printf("=============================================================\n");
    for(i = 0; i <= m; i++)
    {
        switch (list[i])
        {
case 1: printf("星期一 ");
break;
case 2: printf("星期二 ");
break;
case 3: printf("星期三 ");
break;
case 4: printf("星期四 ");
break;
case 5: printf("星期五 ");
break;
case 6: printf("星期六 ");
break;
case 7: printf("星期日 ");
break;
default:
break;
        }
    }
printf("\n\n\n");
}
    else
{
    for(i = k; i <= m; i++)//实验所有可能的list的组合,7!次
    {
swap(&list[k], &list[i]);
perm(list, k + 1, m);
swap(&list[k], &list[i]);
    }
}
}
int main()
{
printf("\n");
printf("注意:\n");
printf(" 1.请按钱、赵、孙、李、周、吴、陈的顺序输入休息每个人的时间。\n");
printf(" 2.输入星期时,请直接输入数字,如要输入'星期一',就用'1'代替,以此类推。\n");
printf(" 3.星期与星期之间用空格隔开,每输入完一个人的休息日,在其后输入0,再按回车继续下一人。\n");
printf("\n");
int list[] = {1, 2, 3, 4, 5, 6, 7};
int i, j;
for(i = 0; i < 7; i++)
{
printf("请输入第 %d 个人的休息时间:\n", i+1);
for(j = 0; j < 7; j++)
{
scanf("%d", &rest[i][j]);
if(rest[i][j] == 0)
break;
}
}
printf("\n\n\n");
perm(list, 0, 6);
getchar();
getchar();
printf("输出完毕,按回车键结束!\n");
return 0;
}

  0.看见swap用来交换

  1.这么一坨代码首先看main,了解到输入的rest数组是每个人的希望的休息时间。

  2.看见用rest【i】[j]与list[i]进行比较,下文将list转换成星期几输出,那么list应该是保存的结果。

     两个for循环是判断list是否可行。对于list[x],查找对应的第x人的愿望单里有没有这个数字,有就找下一个人,全通过了意味着方案可行,下面用来输出list;没有就返回上一层函数;

  3.重点是这里,用了递归 

for(i = k; i <= m; i++)//
    {
swap(&list[k], &list[i]);
perm(list, k + 1, m);
swap(&list[k], &list[i]);

程序的主要思路为尝试从1到7的数字的所有组合,如果符合条件,就输出。这样一共要进行7!次测试。
  那么如何进行从一到七的全排列呢? 先看一下我们怎么全排列 1 2 3。
  一共可以排列的方式如下: 
  1 2 3 
  1 3 2 
  2 1 3
  2 3 1
  3 1 2 
  3 2 1 
  我们让不同的数字分别打头,然后交换剩下的数字。 更近一步:如何进行1到4的全排列呢?

  同样的,我们让不同的数字打头。 
  1 int[3](开头数字1,后面是一个长度为3的数组) 
  ...... 
  2 int[3]
  ...... 
  ...... 
  4 int[3] 
  我们把打头数字相同的看做一组数字,这样一共有4组数字。
   对于每组数字,我们需要将他们尾部的数组全排列,也就是重复四次上面排列1 2 3的方法,注意每次操作对象不同。一共操作4*(3*2)次 
  从 1到5也是同理,我们将他们分为5组。 
   1 [4] 
   2 [4] 
   ..... 
   5 [4] 
  对于每组数,我们将它尾部的数组用上面排列4个元素的方法进行排列,而排列4个元素的方法又要用到排列3个元素的方法,排列3个元素又要用到排列2个元素的方法。
  于是总排列次数为5*4*3*2*1=120次 我们看到,每次排列都要用到比自己更小的数的排列方法,排列x个数方案为x!。  
  现在我们回来看代码。 排列1到7,我们需要排列7!次。首先要把1到7分成七组,让每个数字轮流打头。 
  所以 for{swap..}。(在末尾的时候你必须要把元素换回来,要不换下一个数时数组就乱了。所以结尾也要swap();)
  在这7次循环中,每次你都要用到排列后面6个数的方法,用到6次自己,只需要调用自己,把参数改成6就行了,所以
  for(....)

  swap()

  perm()

  swap()
而排列6个数就要用到排列5个数的方法,这样一直下去函数一共嵌套了7层,第1层执行7遍,第2层执行6遍,以此类推,一共执行7!遍.

——————————————————————————
emmmmmmmm还没懂我就再改改  

没讲明白的水题orz的更多相关文章

  1. 【Floyd(并非水题orz)】BZOJ4093-[Usaco2013 Dec]Vacation Planning

    最近刷水太多标注一下防止它淹没在silver的水题中……我成为了本题,第一个T掉的人QAQ [题目大意] Bovinia设计了连接N (1 < = N < = 20,000)个农场的航班. ...

  2. 史上最明白的 NULL、0、nullptr 区别分析(老师讲N篇都没讲明白的东东),今天终于明白了,如果和我一样以前不明白的可以好好的看看...

    C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL; foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #def ...

  3. 说一说ST表 讲一讲水题

    ST表 一.算法介绍 如何快速求解RMQ问题呢?暴力复杂度O(n),线段树复杂度O(n)~O(logn),要是数据规模达到10^7或者更高呢?我们需要一种可以做到O(1)查询的算法,这时就可以用到ST ...

  4. 搜索 水题&&错误集锦

    引子: 本以为搜索的题目老师也不会检查,结果今天早上loli慢悠悠的说:“请同学们提交一下搜索的题目~”,顿时心旌摇曳,却也只能装作镇定自若的样子,点了点头.. 然后就开始了今天的疯狂做题,虽说题目都 ...

  5. Codeforces Round #190 (Div. 2) 水果俩水题

    后天考试,今天做题,我真佩服自己... 这次又只A俩水题... orz各路神犇... 话说这次模拟题挺多... 半个多小时把前面俩水题做完,然后卡C,和往常一样,题目看懂做不出来... A: 算是模拟 ...

  6. BZOJ USACO 银组 水题集锦

    最近刷银组刷得好欢快,好像都是水题,在这里吧他们都记录一下吧(都是水题大家一定是道道都虐的把= =)几道比较神奇的题到时再列出来单独讲一下吧= =(其实我会说是BZOJ蹦了无聊再来写的么 = =) [ ...

  7. Atcoder 水题选做

    为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...

  8. 【转】POJ百道水题列表

    以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight ...

  9. Disillusioning #1 水题+原题赛(被虐瞎)

    https://vijos.org/tests/542c04dc17f3ca2064fe7718 好一场 水题 比赛啊 t1直接上暴力费用流10分QAQ,虽然一开始我觉得可以不用的,直接dfs可以得出 ...

随机推荐

  1. How to Animate UILabel textColor Properties

    How to Animate UILabel Properties UILabel properties cannot be easy animated due to some various rea ...

  2. PHP实现RabbitMQ消息队列(转)

    本篇文章给大家带来的内容是关于PHP和RabbitMQ实现消息队列的完整代码,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 先安装PHP对应的RabbitMQ,这里用的是 php_a ...

  3. vba批量作图心得1

    1.1:连续有几个图的时候,如果需要设置某一个图的横坐标标签隐藏,要注意将坐标轴标签属性和坐标轴曲线粗细的属性区分开来 1.2:PlotArea里面有left和insideLeft属性,结合两个可以控 ...

  4. Codeforces1099D.Sum in the tree(贪心)

    题目链接:传送门 思路: 一个节点放的数越大,那么以它为根的子树的节点权值之和就越小. 所以我们要在合法的范围内,使偶数层节点的权值尽可能地大.也就是说,令它的权值是子节点的最小值,这样保证了它的子节 ...

  5. html基础js

    HTML中的三把利器的JS 又称为JavaScript,看着好像和Java有点联系,实际上他和java半毛钱关系都没有,JavaScript和我们学习的Python.Go.Java.C++等,都是一种 ...

  6. C语言中的二维数组

    1.二维数组的定义和引用 一. 数据类型 数组名[常量表达式1][常量表达式2]; (1)假如有个二维数组array[n][m],则行下标的取值范围0~n-1 (2)列下标的取值范围0~m-1 (3) ...

  7. 取MySQL结果集的第一条记录

    select * FROM SU_supplycontract t WHERE supplyContractCode="CRM20180813002" limit 1;

  8. SQL学习 存储过程&DUAL表

    CREATE OR REPLACE PROCEDURE 存储过程 转自 https://www.cnblogs.com/lideng/p/3427822.html oracle中dual表的用途介绍 ...

  9. UE4 PostProcessVolume 蓝图操作后期框

    如图找到场景里面的后期框,首先我们要获得它的设置,Settings 大概就是属性的意思.通过Settings设置其它的属性.Set members in PostProcessSetting 就是接口 ...

  10. Web前端学习第二天(cookie 一)

    CookIe安全 cookie一个神奇的机制,无论什么请求中都会带有cookie字段. 可以通过服务器响应头的Set-Cookie字段添加,修改和删除,大多数情况下,客户端通过JavaScript也可 ...