nyist-素数环
来源:互联网 发布:python 字典遍历 编辑:程序博客网 时间:2024/05/18 01:39
素数环
- 描述
有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。
- 输入
- 有多组测试数据,每组输入一个n(0<n<20),n=0表示输入结束。
- 输出
- 每组第一行输出对应的Case序号,从1开始。
如果存在满足题意叙述的素数环,从小到大输出。
否则输出No Answer。 - 样例输入
6830
- 样例输出
Case 1:1 4 3 2 5 61 6 5 2 3 4Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2Case 3:No Answer
开始一上来的思路就是列出所有情况~~~啥都不管直接找
但是想想 6个数组成的6位数 有 6!个
n=20 时 20!一个一个找 ?能不超时?
剪枝,把两边和不是素数去掉 合理 可以
好了 经过我认真分析发现素数和跟我写的zb和 部分和 有一点很大的不同
比如我在部分和中 发现这个数不行 溯回后 再向下查找时 这个数后面就不用了
比如例子
3 21
5 8 13
第一遍 找了 5 8 13 发现不行 回溯 到8 还不行 回溯到 5 还不行回溯 从8开始(8为第一个数)
后面就不用5了
而这个素数和不一样,接下来的搜索 还我要用 还要思考如何在后面继续用到这个数
那我用过就把这个数标记了,如果回溯就取消标记
for循环的时候从头循环
for(int i=pos; i<n; i++) { sum+=a[i]; visit[i]=1; /*printf("%d %d %d\n",pos,i,sum); for(int k=0; k<n; k++) { printf("%d ",visit[k]); } printf("\n");*/ dfs(i+1); sum-=a[i]; visit[i]=0; }
这是部分和问题的中的for循环 从当前递归的数 的下一位开始 前面的数都不用了
好了 素数环要改变策略了
#include<stdio.h>#include<math.h>#include<string.h>int a[30],b[30];int n,j;bool flag;/*int ss(int x){ int l=1; if(x==0||x==1) { x=0; } for(int i=2; i<=sqrt(x); i++) { if(x%i==0) { l=0; } } return l;}*/void dfs(int x){ /*if(ss(a[j]+a[j-1])!=1) { return; }*/ if(x>n) { for(int i=1; i<=n; i++) { printf("%d ",b[i]); } printf("\n"); return ; } for(int i=1; i<n; i++) { if(a[i]==0) { printf("%d$\n",x); a[i]=1; // 标记 表示这个数用过 b[j++]=x; //将当期数存入b中 for(int i=1; i<=n; i++) { printf("%d ",b[i]); } printf("*\n"); dfs(i+1); b[--j]=0; a[i]=0; //去掉标记 for(int i=1; i<=n; i++) { printf("%d ",b[i]); } printf("**\n"); } }}int main(){ while(scanf("%d",&n)!=EOF) { if(n==0) { break; } memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); flag=false; j=1; dfs(1); }}
好了 我写的代码 输出没结果 尴尬
这样 一步一步来 先来输出所有的情况 再判断那种符合条件
那咱们先找出所有的情况 其他的不考虑
简单化
简单化的过程中发现了自己的一个思维错误
(这就是自己dbug的好处)
如果这样写递归 永远也出不了结果
为什么那
我输入3
递归是从第二个数 2 开始的
进去后发现到了x=2 就return 了
虽然我都没用return
过程中根本就没输出结果
改了一下
for(int i=1; i<=n; i++) { if(a[i]==0) { printf("%d$\n",x); a[i]=1; // 标记 表示这个数用过 b[j++]=x; //将当期数存入b中
发现有一种情况可以输出 但是另外的情况的最后的一个数都输不出来
推理一下 可能是回溯的问题
又修改了一个地方 原来的
dfs(i+1)改为
dfs(x+1)好了 就可以输出所有排序情况
代码
#include<stdio.h>#include<math.h>#include<string.h>int a[30],b[30];int n,j;bool flag;/*int ss(int x){ int l=1; if(x==0||x==1) { x=0; } for(int i=2; i<=sqrt(x); i++) { if(x%i==0) { l=0; } } return l;}*/void dfs(int x){ /*if(ss(a[j]+a[j-1])!=1) { return; }*/ if(x>n) { for(int i=1; i<=n; i++) { printf("%d ",b[i]); } printf("\n"); return ; } for(int i=1; i<=n; i++) { if(a[i]==0) { //printf("%d$\n",x); a[i]=1; // 标记 表示这个数用过 b[j++]=i; //将当期数存入b中 /*for(int i=1; i<=n; i++) { printf("%d ",a[i]); } printf("*\n");*/ dfs(x+1); b[--j]=0; a[i]=0; //去掉标记 /*for(int i=1; i<=n; i++) { printf("%d ",a[i]); } printf("**\n");*/ } }}int main(){ while(scanf("%d",&n)!=EOF) { if(n==0) { break; } memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); //flag=false; j=1; dfs(1); }}纯手工 自己想 ,自己dbug 真不容易!!!!!
分析一下为什么这样改 还有为什么会在2时候就return
如果 是 dfs(i+1)的话如果我第二个数选3 即选了 1 3
本来该选3 了 可是我dfs(i+1) 就是dfs(4) 就符合return条件了
直接跳出
下面添枝加叶就完成这道题了
#include<stdio.h>#include<math.h>#include<string.h>int a[30],b[30];int n,j;bool flag;int ss(int x){ int l=1; if(x==0||x==1) { x=0; } for(int i=2; i<=sqrt(x); i++) { if(x%i==0) { l=0; } } return l;}void dfs(int x){ if(a[1]!=1) { return; } if(ss(a[j]+a[j-1])!=1&&j>1) { return; } if(x>n) { flag=true; for(int i=1; i<=n; i++) { printf("%d ",b[i]); } printf("\n"); return ; } for(int i=1; i<=n; i++) { if(a[i]==0) { //printf("%d$\n",x); a[i]=1; // 标记 表示这个数用过 b[j++]=i; //将当期数存入b中 /*for(int i=1; i<=n; i++) { printf("%d ",a[i]); } printf("*\n");*/ dfs(x+1); b[--j]=0; a[i]=0; //去掉标记 /*for(int i=1; i<=n; i++) { printf("%d ",a[i]); } printf("**\n");*/ } }}int main(){ while(scanf("%d",&n)!=EOF) { if(n==0) { break; } memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); flag=false; j=1; dfs(1); if(!flag) { printf("No Answer\n"); } }}
输出的全是No Answer
无语...........
发现了
if(a[1]!=1) { return; }
这个判断语句是有毛病的 我第一次进来
直接就return回去了 因为 a【1】还是0那 直接我就不递归了 那不就WA了
修改后代码
#include<stdio.h>#include<math.h>#include<string.h>int a[30],b[30];int n,j,step=0,time;bool flag;int jude(int a){ int p=1; if(a==1||a==0) { return 0; } for(int i=2; i<=sqrt(a); i++) { if(a%i==0) { p=0; } } return p;}void dfs(int x){ if(j>=2&&jude(b[j-1]+b[j-2])!=1) { return; } if(x>=n&&jude(b[n-1]+1)!=1) { return; } if(x>=n) { if(time==1) { printf("Case %d:\n",step); time++; } for(int i=0; i<n; i++) { printf("%d ",b[i]); } printf("\n"); flag=true; return ; } for(int i=2; i<=n; i++) { if(a[i]==0) { a[i]=1; // 标记 表示这个数用过 b[j++]=i; //将当期数存入b中 dfs(x+1); b[--j]=0; a[i]=0; //去掉标记 } }}int main(){ while(scanf("%d",&n)!=EOF) { step++; if(n==0) { break; } memset(a,0,sizeof(a)); b[0]=1,b[1]=2; j=1,time=1; flag=false; dfs(1); if(!flag) { printf("Case %d:\n",step); printf("No Answer\n"); } } return 0;}
万事OK 提交
TL 超时!!
好了 发现一个规律
凡是奇数的 都是 no answer
因为奇数个数的数 组成环 必须会有2个奇数组合在一起
奇数加奇数为偶数 直接就不是素数了
再提交
猝不及防 一个WA
因为 当n=1时 应该输出1
这输出的 no answer
╮(╯▽╰)╭
AC代码
#include<stdio.h>#include<math.h>#include<string.h>int a[30],b[30];int n,j,step=0,time;bool flag;int jude(int a){ int p=1; if(a==1||a==0) { return 0; } for(int i=2; i<=sqrt(a); i++) { if(a%i==0) { p=0; } } return p;}void dfs(int x){ if(j>=2&&jude(b[j-1]+b[j-2])!=1) { return; } if(x>=n&&jude(b[n-1]+1)!=1) { return; } if(x>=n) { if(time==1) { printf("Case %d:\n",step); time++; } for(int i=0; i<n; i++) { printf("%d ",b[i]); } printf("\n"); flag=true; return ; } for(int i=2; i<=n; i++) { if(a[i]==0) { a[i]=1; // 标记 表示这个数用过 b[j++]=i; //将当期数存入b中 dfs(x+1); b[--j]=0; a[i]=0; //去掉标记 } }}int main(){ while(scanf("%d",&n)!=EOF) { step++; if(n==0) { break; } if(n==1) { printf("Case %d:\n",step); printf("1\n"); continue; } if(n%2==1) { printf("Case %d:\n",step); printf("No Answer\n"); continue; } memset(a,0,sizeof(a)); b[0]=1,b[1]=2; j=1,time=1; flag=false; dfs(1); if(!flag) { printf("Case %d:\n",step); printf("No Answer\n"); } } return 0;}
总结
小白我 明白了 memset 只能把数组重置为 0 或者 -1 其他的都是乱码
还有 做题 从基础的开始
一道题也许对你很难
那你一步一步实现
就如这一题
先找出所有情况,再排除一些
- nyist-素数环
- nyist 488 素数环(搜索+回溯)
- nyist 因子和 (素数)
- nyist
- hdu1016 (素数环)(深度优先搜索)另附:http://acm.nyist.net/JudgeOnline/problem.php?pid=488
- nyist-基础语言-题目24(素数距离问题)
- nyist 26 孪生素数问题(筛选法)
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- 素数环
- HDFS的运行原理
- C# MDI编程中子窗体调用子窗体的问题
- golang 使用gops进行程序监控
- H5移动前端开发常用高能css3汇总
- sql数据库基本语句
- nyist-素数环
- caffe训练cifar10遇到./build/tools/caffe: not found 错误解决方法
- 获取手机摄像机图片的缩略图方法,防止内存溢出异常
- ==和equal的比较
- 产品需求注意要点
- mysql 性能优化方法汇总
- CMD命令大全
- data binding
- android工程师招聘-工作职责