有一道解释程序的水题没给非计算机专业的同学讲明白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. Asp.net MVC Form认证,IIS改成集成模式后,FormsAuthentication.SetAuthCookie无效,Request.IsAuthenticated值,始终为false,页面提示HTTP 错误 401.0 - Unauthorized,您无权查看此目录或页面

    最近公司领导要求,IIS网站要由经典模式改为集成模式,以提高性能.改完之后,登录成功跳转到主页之后,页面提示“”HTTP 错误 401.0 - Unauthorized“,“您无权查看此目录或页面”, ...

  2. 新增和编辑clob字段

    #region 新的数据新增和修改方法 /// <summary> /// 添加信息 /// </summary> /// <returns></return ...

  3. 实验十 ZStack 网状网络实验

    实验十 ZStack 网状网络实验[实验目的]1. 了解 ZigBee 网状网络结构2. 掌握构建网状网络的方法[实验设备]1. 装有 IAR 开发工具的 PC 机一台2. 实验箱一台3. CCDeb ...

  4. 不同组的id列表的汇总对比

    需求: 三个不同的dfs中存在不同的多个节点id,现在需要求出不同的dfs之间的节点对应关系,比如,哪些节点在某一个dfs,但是不在另一个dfs中 思路: 一. 如果是单纯计算dfs中节点数量,则可以 ...

  5. 第一次Scrum冲刺——Life in CCSU

    一.第一次Scrum任务 首先集体讨论确定全局规划,然后进行切割分工,按照规划实现全部功能.现在基于用户的基本需求做一部分. 二.用户故事 1.用户打开APP,进入登录界面: 2.用户输入账号和密码: ...

  6. Spock - Document -01- introduction & Getting Started

    Introduction Peter Niederwieser, The Spock Framework TeamVersion 1.1 Spock is a testing and specific ...

  7. Linux 的终端及设置

    Linux 的终端及设置 终端是一种字符型设备,有多种类型,通常使用tty 来简称各种类型的终端设备.终端特殊设备文件一般有以下几种: /dev/ttySn 串行端口终端 (Serial Port T ...

  8. JavaScript 查找图中连接两点的所有路径算法

    1.把图看成以起点为根节点的树 2.使用深度遍历算法遍历路径 3.遍历到节点为目标节点时,保存这条路径 find2PointsPath(sourceId, targetId) { const { no ...

  9. 一道考查request导致的安全性问题的ctf题

    这道题是在看红日安全团队的代码审计系列文章时碰到的,感觉挺有意思的,所以做了下.题目代码如下 //index.php <?php require 'db.inc.php'; function d ...

  10. centos 终端字体错位个别字母中间有间隔的解决

    问题描述: linux系统:centos 终端:图形界面终端,通过startx启动 现象:通过终端输入的字体有重叠,字母之间的间隔也很大.由于字体安装不正确导致. 解决方法:通过下面字体的安装命令可以 ...