蛮力法——狱吏问题

来源:互联网 发布:java课程设计题目 编辑:程序博客网 时间:2024/05/19 16:06

题目大意:狱吏问题)某王国对囚犯进行大赦,让一狱吏n次通过一排锁着的n间牢房,每通过一次按所定规则转动门锁,每转动一次,原来锁着的被打开,原来打开的被锁上;通过n次后,门锁开着的,牢房中的犯人放出,否则犯人不得获释.转动门锁的规则是这样的,第一次通过牢房,要转动每一把门锁,即把全部锁打开;第二次通过牢房时,从第二间开始转动,每隔一间转动一次;第k次通过牢房,从第k间开始转动,每隔k-1 间转动一次;问通过n次后,那些牢房的锁仍然是打开的?

三种方法:
所有方法中锁的状态:1代表锁着,0代表开着

1、纯暴力法
C++代码:

#include<iostream>using namespace std;int main(){    int n,*prisoner;    cin>>n;    prisoner=new int[n+1];    for(int i=0;i<=n;i++)        prisoner[i]=1;    for(int i=1;i<=n;i++)    //i--->表示狱吏是第几轮走过        for(int j=i;j<=n;j=j+i)          //j--->需要改变的锁的编号              prisoner[j]=1-prisoner[j];    for(int i=1;i<=n;i++)        if(prisoner[i]==0)            cout<<i<<" ";    return 0;}

2、利用因子数
C++代码:

     //利用因子数的个数得出每个编号的锁中间变换状态的次数     //eg  i=4时,它的因子有1,2,4,所以他在第1,2,4轮时会变换状态
#include<iostream>using namespace std;int main(){    int n,*prisoner;    cin>>n;    prisoner=new int[n+1];    for(int i=0;i<=n;i++)        prisoner[i]=1;    for(int i=1;i<=n;i++)    {        int count=1;        for(int j=2;j<=i;j++)            if(i%j==0)                count++;        if(count%2==0)            prisoner[i]=1;        else            prisoner[i]=0;    }    for(int i=1;i<=n;i++)        if(prisoner[i]==0)            cout<<i<<" ";    return 0;}

3、找规律
C++代码:

    //利用规律来判断    //规律:当锁的标号为一个数的平方时,那么最后它会开着

eg.(其中1代表锁着,0代表开着)
锁的标号:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
最后状态:0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0

#include<iostream>#include<math.h>using namespace std;int main(){    int n,*prisoner;    cin>>n;    prisoner=new int[n+1];    for(int i=0;i<=n;i++)        prisoner[i]=1;    for(int i=1;i<=sqrt(n);i++){        int temp=i*i;        if(temp<=n)            prisoner[temp]=0;    }    for(int i=1;i<=n;i++)        if(prisoner[i]==0)            cout<<i<<" ";    return 0;}
原创粉丝点击