山西省城乡住房和建设厅网站首页杭州seo专员
2026/2/20 1:13:58 网站建设 项目流程
山西省城乡住房和建设厅网站首页,杭州seo专员,wordpress f5,首页页面设计模板题目描述2k 个人站成一圈#xff0c;从某个人开始数数#xff0c;每次数到 m 的人就被杀掉#xff0c;然后下一个人重新开始数#xff0c;直到最后只剩一个人。现在有一圈人#xff0c;k 个好人站在一起#xff0c;k 个坏人站在一起。从第一个好人开始数数。你要确定一个…题目描述2k 个人站成一圈从某个人开始数数每次数到 m 的人就被杀掉然后下一个人重新开始数直到最后只剩一个人。现在有一圈人k 个好人站在一起k 个坏人站在一起。从第一个好人开始数数。你要确定一个最小的 m使得在 k 个坏人均被杀死时 k 个好人都存活。输入格式一行一个整数 k。输出格式一行一个整数 m。输入 3 输出 5 输入 4 输出 30 说明/提示 0k14其中前 k 个人是好人编号 1~k· 后 k 个人是坏人编号 k1~2k· 从第一个人好人编号1开始数数· 每次数到 m 的人被处决然后从下一个人重新开始数· 要求找到一个最小的 m使得在处决完 k 个人后剩下的 k 个人全是好人· 换句话说前 k 次处决必须全是坏人#includestdio.h #define MAX_K 13 #define MAX_N (2*MAX_K)//代表的是总人数最多为26个人。 int check(int k,int m) { int next[MAX_N2],prev[MAX_N2];//next[]表示每个人的后者prev[]代表每个人的前者 int n2*k;//总人数 int i; for(i1;in;i){//给每个人都用遍历来赋上编号 next[i]i1;//编号为i的人的后一个人的编号为i1 prev[i]i-1;//编号为i的人的前一个人的编号为i-1 } next[n]1;//编号为2k的人即为最后一个人的下一个人编号为第一个人的编号1 prev[1]n;//编号为1的人的前一个人的编号为2k即n int p1;//从编号1开始数 int Ln;//代表剩余人数 for(i0;ik;i){//循环k次是因为要处决k个坏人 int steps(m-1)%L;//计算实际需要走的步数即走这些步才数到m编号 int curp;//当前位置 int preprev[p];//当前位置的前一个 int j; for(j0;jsteps;j){走steps步找到被处决的人数 precur;// curnext[cur]; } if(curk){//如果处决的人编号小于k即处决的是好人不符合题意 return 0; } next[pre]next[cur];//前一个位置的下一个即被处决的人的位置变成了被处决的人的下一个人 prev[next[cur]]pre;//被处决的人的下一个人的前一个人变成了被处决的人的前面的人 pnext[cur];//被处决的人排除之后下一个开始计数的位置变成了被处决的人的下一个人 L--;//剩余人数减少一个人 } return 1; } int main() { int k; scanf(%d,k); int m; //代表数到m的人即会被处决杀死 for(mk1;;m){//因为第一个人是好人m肯定不会是应该被处决的人。对m开始进行枚举如果碰到符合条件的m即符合上述函数则就输出m if(check(k,m)){ printf(%d\n,m); break;//因为要求的是最小的m所以只要碰到第一个符合题意的输出就不用再在后面判断了 } } return 0; }一.上述代码采用双向循环链表。什么是双向循环链表双向循环链表是一种特殊的数据结构· 双向每个节点既知道下一个节点也知道上一个节点· 循环链表的首尾相连形成一个环· 链表一系列通过指针连接的数据节点二.for(i0;ik;i){int steps(m-1)%L;int curp;//cur永远记录开始计数的人的位置int preprev[p];int j;for(j0;jsteps;j){precur;//前一个人更新为当前位置因为当前位置的人已经被杀死了curnext[cur];//当前开始计时位置为之前被杀死的人的后一个人}//循环结束cur就是被处决的人if(curk){return 0;}next[pre]next[cur];prev[next[cur]]pre;pnext[cur];L--;}详细解析上述部分代码1.因为从编号1开始走走到编号2只需要走1步即找到2只需要走1步那么找到m只需要走m-1步。所以当m-1L时走的步数就是m-1当人数为L时走L步会回到起点当m-1大于L时走的步数即为余数。刚好满足上述式子。2.为什么初始化 pre prev[p]· 在后续的循环中pre 需要始终是 cur 的前一个人· 开始时cur p所以 pre 应该是 p 的前一个人示例初始状态p1,//从编号1开始数数 L6,//剩余人数 m3//每次数到m的人就会被杀掉steps (3-1)%6 2//数到m只需要实际走steps步循环过程j0: pre1, cur2j1: pre2, cur3结果cur3被处决的人上述循环结束后cur表示的当前位置的人被处决然后要想办法把该处决的人的编号排除。方法即为把被处决的位置变成被处决的后一个人但后一个人的编号不变只是位置改变。当steps0时即循环不执行直接处决当前位置cur即p当m1时总是处决当前位置即p1时被处决下次计数从第二个人开始计数1仍被处决即当前位置被处决。steps (1-1)%L 0cur p被处决三.最后总结一下上述代码的思路用遍历对每个人进行编号因为后续要利用双循环所以要处理边界问题。因为排除被处决的人后要重新从下一个人开始计数所以要定义一个变量p来表示从哪一个开始计数。然后对每一个人开始进行遍历找应该被处决的人。定义走多少步可以找到处决者为后续遍历找处决者提供基础。肯定要定义一个变量表示被处决者又因为有双循环前一个后一个当前者索性把被处决者定义为当前者当前者初始化为计数的位置而这刚好便于去除当前者后的计数位置为下一个人同时更好找到处决者时好改变前者后者的位置。既然有前者和后者所以要定义。最后去除当前者改变剩余者的位置。最后直到把所有的坏人都除掉之后当前位置变成小于k的值跳出该函数。只要输入的m符合题意则就会返回1,用于后续主函数的输出。写这篇的时候好痛苦啊用了两个小时。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询