hdu1016 Prime Ring Problem

来源:互联网 发布:智能家居 知乎 编辑:程序博客网 时间:2024/06/09 11:50
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.


 

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.
 

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
这题必须mark一记啊啊啊!!!
本来挺简单的思路,它就是那么拽!
代码:
# include <iostream># include <cstring>using namespace std;int visited[30],buffer[30],m;bool prime (int a,int b)//没问题{    int c,i;    c = a+b;    for (i = 2;i*i<=c;i++)    {        if (c%i == 0)        {            return 0;        }    }    return 1;}//void dfs(int step){    int i;   if (step> m && prime(1,buffer[m-1]))//所以位置已排满且第一位与最后一位之和为素数   {       for(i = 0;i<m-1;i++)//       {           cout<<buffer[i]<<" ";       }       cout<<buffer[m-1]<<endl;//   }   else   {       for (i = 2;i<=m;i++)//从开始搜索一直到m       {           buffer[step-1] = i;           if(!visited[i] && prime(buffer[step-2],buffer[step-1]))//当前位与前一位和为素数且没有被访问过           {               visited[i] = 1;//标记为已搜索               dfs(step+1);//开始为下一个序列位置搜索               visited[i] = 0;//回溯要恢复前一步的状态           }       }   }}int main (){    int cnt = 0;    int i;    while (cin>>m && m)    {      cnt++;       memset(visited,0,sizeof(visited));//或者memset(visited,0,sizeof(visited));       visited[1] = 1;//表示已经使用       buffer[0] = 1;       cout<<"Case "<<cnt<<":"<<endl;       dfs(2);       cout<<endl;    }    return 0;}
这是AC了的,上次因为cin比scanf慢导致不能ac,从此就用scanf了,于是我原来在while里面写的是while(scanf("%d",n) && n)
拿以前ac过的题目比较思路差不多啊,就是超时!!崩溃!

最后只要写成while(~scanf("%d",n) && n)就好了

上面两者的区别在于:
 前者是当输入n为0的时候结束程序
后者是当没有输入的时候结束程序
 对于大多数函数来说都有一个返回值 
 cin的返回值是成功输入的个数, 没有输入就返回0,于是while里面的表达式是0., 就结束
但是scanf呢也是成功输入的个数,但是没有输入不是返回0,而是返回-1


好吧,涨姿势了

下面还有一个方法,效率高,打表方法,因为输入的个数最大是20,只要打表到40的素数表就行了。

代码

#include<cstring>#include<iostream>//#include<algorithm>#include<cstdio>#include<cmath>int a[22];int visit[22];int prime[41]={0,1,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,0,0};int n;using namespace std;void dfs( int num)//长度,当前是第几个{    int i;    if(num > n  && prime[a[1]+a[n]])//长度满足且首尾和为素数    {        for (i = 1; i < n; i++)        {            cout << a[i] << " ";        }        cout << a[n] << endl;    }    for (i = 2; i <= n; i++)//遍历    {        a[num] = i;        if(prime[a[num-1]+i] && !visit[i])        {            visit[i] = 1;            dfs(num+1);            visit[i] = 0;         }    }}int main(){   int cnt = 0;   while (cin >> n && n )   {       cnt++;       memset(visit,0,sizeof(visit));       memset(a,0,sizeof(a));       a[1] = 1;       visit[1] = 1;       cout <<"Case "<< cnt << ":" << endl;       dfs(2);       cout << endl;   }   return 0;}
碎碎念:数据不大的情况下多想想打表。。。。




0 0
原创粉丝点击