2020
2016-04-15 20:20
295 查看
2020
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.<br><br>Note: the number of first circle should always be 1.<br><br><img src=../../data/images/1016-1.gif><br>
Input
n (0 < n < 20).<br>
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.<br><br>You
are to write a program that completes above process.<br><br>Print a blank line after each case.<br>
Sample Input
6<br>8<br>
Sample Output
Case 1:<br>1 4 3 2 5 6<br>1 6 5 2 3 4<br><br>Case 2:<br>1 2 3 8 5 6 7 4<br>1 2 5 8 3 4 7 6<br>1 4 7 6 5 8 3 2<br>1 6 7 4 3 8 5 2<br>
Source
Asia 1996, Shanghai (Mainland China)
思路:一般是要先找出所有的排列,然后使用DFS算法筛选。但是我提交了之后,显示时间超出要求。我在网上看了一下,优化的算法基本上就是一边拿排列一边搜索,这样可以减少不少的时间。另外,因为题目中给定了范围,把范围内的素数全部列出来,然后查表判断,也可以节省很多的时间。
若输入的数据为奇数,那么没有满足条件的排列,可以直接返回。
AC代码:
#include <iostream>
#include<cstdio>
using namespace std;
// 小于37的所有素数
int prime[38]=
{
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,
};
void Output(int a[], int n)
{
for(int i=0;i<n;i++)
{
if(i==n-1)
cout<<a[i];
else
cout<<a[i]<<" ";
}
cout<<endl ;
}
bool IsOk(int a[], int lastIndex, int curValue)
{
if(lastIndex<0)
return true ;
if(!((curValue+a[lastIndex]) & 1))
return false ;
if(!prime[a[lastIndex]+curValue])
return false ;
for(int i = 0; i <= lastIndex; i++)
if(a[i] == curValue)
return false ;
return true ;
}
void dfs(int a[], int n, int t)
{
if(n & 1)
return;
if(t==n)
{
if(prime[a[0]+a[n-1]])
Output(a,n);
}
else
{
for(int i=2;i<=n;i++)
{
a[t]=i;
if(IsOk(a,t-1,i))
dfs(a,n,t+1);
}
}
}
int main()
{
int a[20],n,k=1;
while(scanf("%d",&n)!=EOF)
{
cout<<"Case "<<k<<":"<<endl;
k++;
a[0]=1;
dfs(a,n,1);
printf("\n");
}
return 0 ;
}
今天想写一下感悟,不是总结。
经常听别人说重要的在于思路。可是有时候就算有了思路,真正的实现起来还是很困难的。就像这个题,其实弄明白题意之后就知道要用深搜,中规中矩的用了之后,最开始是WA,然后是超时。优化也是费了老大劲,到最后几乎把最开始写的代码全都改了一遍。。。。。。好困难。。。。
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.<br><br>Note: the number of first circle should always be 1.<br><br><img src=../../data/images/1016-1.gif><br>
Input
n (0 < n < 20).<br>
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.<br><br>You
are to write a program that completes above process.<br><br>Print a blank line after each case.<br>
Sample Input
6<br>8<br>
Sample Output
Case 1:<br>1 4 3 2 5 6<br>1 6 5 2 3 4<br><br>Case 2:<br>1 2 3 8 5 6 7 4<br>1 2 5 8 3 4 7 6<br>1 4 7 6 5 8 3 2<br>1 6 7 4 3 8 5 2<br>
Source
Asia 1996, Shanghai (Mainland China)
思路:一般是要先找出所有的排列,然后使用DFS算法筛选。但是我提交了之后,显示时间超出要求。我在网上看了一下,优化的算法基本上就是一边拿排列一边搜索,这样可以减少不少的时间。另外,因为题目中给定了范围,把范围内的素数全部列出来,然后查表判断,也可以节省很多的时间。
若输入的数据为奇数,那么没有满足条件的排列,可以直接返回。
AC代码:
#include <iostream>
#include<cstdio>
using namespace std;
// 小于37的所有素数
int prime[38]=
{
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,
};
void Output(int a[], int n)
{
for(int i=0;i<n;i++)
{
if(i==n-1)
cout<<a[i];
else
cout<<a[i]<<" ";
}
cout<<endl ;
}
bool IsOk(int a[], int lastIndex, int curValue)
{
if(lastIndex<0)
return true ;
if(!((curValue+a[lastIndex]) & 1))
return false ;
if(!prime[a[lastIndex]+curValue])
return false ;
for(int i = 0; i <= lastIndex; i++)
if(a[i] == curValue)
return false ;
return true ;
}
void dfs(int a[], int n, int t)
{
if(n & 1)
return;
if(t==n)
{
if(prime[a[0]+a[n-1]])
Output(a,n);
}
else
{
for(int i=2;i<=n;i++)
{
a[t]=i;
if(IsOk(a,t-1,i))
dfs(a,n,t+1);
}
}
}
int main()
{
int a[20],n,k=1;
while(scanf("%d",&n)!=EOF)
{
cout<<"Case "<<k<<":"<<endl;
k++;
a[0]=1;
dfs(a,n,1);
printf("\n");
}
return 0 ;
}
今天想写一下感悟,不是总结。
经常听别人说重要的在于思路。可是有时候就算有了思路,真正的实现起来还是很困难的。就像这个题,其实弄明白题意之后就知道要用深搜,中规中矩的用了之后,最开始是WA,然后是超时。优化也是费了老大劲,到最后几乎把最开始写的代码全都改了一遍。。。。。。好困难。。。。
相关文章推荐
- BNUOJ-49098-神奇的身高
- UTF-8编码格式导致编码GBK的不可映射字符问题
- 欢迎使用CSDN-markdown编辑器
- 《Deep Learning》中文翻译总结
- Python 3.5.1发邮件
- hihoCoder 1051 补提交卡(贪心枚举)
- 构建之法阅读笔记03
- java乱码问题
- 链表的艺术——Linux内核链表分析
- 欢迎使用CSDN-markdown编辑器
- java.lang.ref包源码分析(一):类结构
- iOS小技巧 - 调换按钮中文字与图标的位置(自定义button,重写两个方法)
- 7.3.4 friend class
- bzoj 3609: [Heoi2014]人人尽说江南好 数学
- Android 框架启动流程
- STL学习笔记——序列式容器
- 在Windows上安装TimesTen
- 删除链表中重复的结点
- Java IO5:序列化与反序列化
- 栈的压入、弹出序列