hdu 1016 Prime Ring Problem
来源:互联网 发布:psd下载软件 编辑:程序博客网 时间:2024/03/28 20:36
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14516 Accepted Submission(s): 6623
Total Submission(s): 14516 Accepted Submission(s): 6623
Problem Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
You are to write a program that completes above process.
Print a blank line after each case.
Sample Input
68
Sample Output
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 2
题意: 有N个数字, 依次为1~N, 然后要令这些数字练成一个圆圈, 并且要相邻两个数字的和是一个素数,将所有情况依次输出,并且都是从 1 开始输出。
思路: 两个偶数 或者 两个奇数相加是个偶数, 偶数一定不是素数, 所以N 为奇数时,是没有满足的数字串,输出空行。
然后就用 递归回溯 依次暴力一遍。 每确定一个数字就到下个数字, 满了n个就输出, 回溯的上一个,看还有无其他符合的数字。
深搜, 每次只要考虑 当前要确定的数字 和 上一个确定的数字 的和是否为素数, 和数字是否重复用过。
模拟 N = 6;(希望耐心看)
首先 : 1 是确定的。
数组 : num[] = 1 __ __ __ __ __; visitied[] = 1 0 0 0 0 0;
然后开始递归了(深搜) 每次都从 2 (i == 2) 数字开始找。 判断 i 与 上个确定的数 是否满足条件 if( (i + num[x - 1]) 是素数 && i 未被访问(使用,出现)
结果 是: num[] = 1 2 __ __ __ __; visited[] = 1 1 0 0 0 0;
然后递归到下一个要确定的数字; 同理
结果是: num[] = 1 2 3 __ __ __; visited[] = 1 1 1 0 0 0 ;
接着依次是: num[] = 1 2 3 4 __ __; visited[] = 1 1 1 1 0 0;
接着找不到了 因为 4 与 5 和 6 都是合数。4位置就退出递归,将4位置的数字回溯,visited[i][j] = 0; 比较为未访问: num[] = 1 2 3 __ __ __; visited[] = 1 1 1 0 0 0;
退到3后, 3 与 5 和 6 的和都是合数,同理 回溯: num[] = 1 2 __ __ __ __; visited[] = 1 1 0 0 0 0;
退到2后,2 与 5 的和是素数 num[] = 1 2 5 __ __ __; visited[] = 1 1 0 0 1 0;
接着递推: num[] = 1 2 5 6 __ __; visited[] = 1 1 0 0 1 1;
6与 3 和 4 的和都是合数 回溯: num[] = 1 2 5 __ __ __; visited[] = 1 1 0 0 1 0;
5 已经循环到 6 了 退出递归。 回溯:1 2 __ __ __ __;
2 和 6 的和是合数:1 4 __ __ __ __(继续循环) -> 1 4 3 __ __ __ (递归)-> 1 4 3 2 __ __ (递归) -> 1 4 3 2 5 __ (递归) -> 1 4 3 2 5 6 (递归);
满了, 判断头尾的和是否为素数 1 + 6 == 素数 则输出: 1 4 3 2 5 6
然后退出递归,继续回溯: 1 4 3 2 5 __ -> 1 4 3 2 __ __ (回溯)-> 1 4 3 __ __ __(回溯) -> 1 4 __ __ __ __(回溯) -> 1 6 __ __ __ __(继续循环)
然后继续递归 1 6 5 __ __ __ (递归) -> 1 6 5 2 __ __(递归) -> 1 6 5 2 3 __ (递归) -> 1 6 5 2 3 4(递归);
满了, 同理 1 + 4 == 素数 输出: 1 6 5 2 3 4;
继续 回溯:1 6 5 2 3 __ -> 1 6 5 2 __ __ -> 1 6 5 __ __ __ -> 1 6 __ __ __ __ -> 1 __ __ __ __ __ (循环完退出最外面的dfs(), 程序退出);
递归 可以理解成 深搜, 往更里深搜, 回溯可以理解成 将递归的所访问的 恢复到没访问。
思路: 两个偶数 或者 两个奇数相加是个偶数, 偶数一定不是素数, 所以N 为奇数时,是没有满足的数字串,输出空行。
然后就用 递归回溯 依次暴力一遍。 每确定一个数字就到下个数字, 满了n个就输出, 回溯的上一个,看还有无其他符合的数字。
深搜, 每次只要考虑 当前要确定的数字 和 上一个确定的数字 的和是否为素数, 和数字是否重复用过。
模拟 N = 6;(希望耐心看)
首先 : 1 是确定的。
数组 : num[] = 1 __ __ __ __ __; visitied[] = 1 0 0 0 0 0;
然后开始递归了(深搜) 每次都从 2 (i == 2) 数字开始找。 判断 i 与 上个确定的数 是否满足条件 if( (i + num[x - 1]) 是素数 && i 未被访问(使用,出现)
结果 是: num[] = 1 2 __ __ __ __; visited[] = 1 1 0 0 0 0;
然后递归到下一个要确定的数字; 同理
结果是: num[] = 1 2 3 __ __ __; visited[] = 1 1 1 0 0 0 ;
接着依次是: num[] = 1 2 3 4 __ __; visited[] = 1 1 1 1 0 0;
接着找不到了 因为 4 与 5 和 6 都是合数。4位置就退出递归,将4位置的数字回溯,visited[i][j] = 0; 比较为未访问: num[] = 1 2 3 __ __ __; visited[] = 1 1 1 0 0 0;
退到3后, 3 与 5 和 6 的和都是合数,同理 回溯: num[] = 1 2 __ __ __ __; visited[] = 1 1 0 0 0 0;
退到2后,2 与 5 的和是素数 num[] = 1 2 5 __ __ __; visited[] = 1 1 0 0 1 0;
接着递推: num[] = 1 2 5 6 __ __; visited[] = 1 1 0 0 1 1;
6与 3 和 4 的和都是合数 回溯: num[] = 1 2 5 __ __ __; visited[] = 1 1 0 0 1 0;
5 已经循环到 6 了 退出递归。 回溯:1 2 __ __ __ __;
2 和 6 的和是合数:1 4 __ __ __ __(继续循环) -> 1 4 3 __ __ __ (递归)-> 1 4 3 2 __ __ (递归) -> 1 4 3 2 5 __ (递归) -> 1 4 3 2 5 6 (递归);
满了, 判断头尾的和是否为素数 1 + 6 == 素数 则输出: 1 4 3 2 5 6
然后退出递归,继续回溯: 1 4 3 2 5 __ -> 1 4 3 2 __ __ (回溯)-> 1 4 3 __ __ __(回溯) -> 1 4 __ __ __ __(回溯) -> 1 6 __ __ __ __(继续循环)
然后继续递归 1 6 5 __ __ __ (递归) -> 1 6 5 2 __ __(递归) -> 1 6 5 2 3 __ (递归) -> 1 6 5 2 3 4(递归);
满了, 同理 1 + 4 == 素数 输出: 1 6 5 2 3 4;
继续 回溯:1 6 5 2 3 __ -> 1 6 5 2 __ __ -> 1 6 5 __ __ __ -> 1 6 __ __ __ __ -> 1 __ __ __ __ __ (循环完退出最外面的dfs(), 程序退出);
递归 可以理解成 深搜, 往更里深搜, 回溯可以理解成 将递归的所访问的 恢复到没访问。
#include <stdio.h>#include <string.h>#define max_size 25int n, count = 1, num[max_size], visited[max_size];int p[40] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0};void dfs(int x) { if(x > n && p[1 + num[n]]) { printf("%d", num[1]); for(int i = 2; i <= n; ++i) printf(" %d", num[i]); printf("\n"); return; } for(int i = 2; i <= n; ++i) { if(!visited[i] && p[num[x - 1] + i]) { visited[i] = 1; num[x] = i; dfs(x + 1); visited[i] = 0; } }}int main() { while(~scanf("%d", &n)) { memset(visited, 0, sizeof(visited)); num[1] = 1; printf("Case %d:\n", count++); if(n % 2 == 0) dfs(2); printf("\n"); }}
- hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- HDU 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- HDU-1016 prime ring problem
- hdu 1016Prime Ring Problem
- hdu 1016 Prime Ring Problem
- HDU-1016 Prime Ring Problem
- HDU-1016-Prime Ring Problem
- hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- Hdu 1016 Prime Ring Problem
- hdu 1016 Prime Ring Problem
- Hdu 1016 - Prime Ring Problem
- HDU 1016 Prime Ring Problem
- 秋雨寄相思
- SQL Server的事务和错误处理
- 文件操作API函数汇总
- Android 软键盘盖住输入框的问题
- struts.xml
- hdu 1016 Prime Ring Problem
- SendEmail javaEmail发送邮件
- iOS开发笔记--正则表达式NSRegularExpression
- hdu 4282 爆搜
- 获得文件大小
- 设计模式遵循的七大原则
- eclipse代码提示,代码自动完成等功能
- Ubuntu 10.10 启动到字符界面
- linux kernel网络驱动