hdu1016 Prime Ring Problem

27 篇文章 0 订阅
4 篇文章 0 订阅
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
  
  
6 8
 

Sample Output
  
  
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 2: 1 2 3 8 5 6 7 4 1 2 5 8 3 4 7 6 1 4 7 6 5 8 3 2 1 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值