现流行头脑风暴,再来一个

legend115599 2009-09-12 01:17:10
现有一巨型时钟,一人站在1点处,从1点出发,顺时针往后走当前点数,如从1点出发,则走1步到达2点,然后再走2步到达4点,然后再走4步到达8点,然后再走8步又到了4点,此时他将在4和8之间无限循环。现假设时钟个点位置可以随意互相调动,调动后该人同样从1点出发(此时1点不一定在原来的标准1点处),按先前规律前进,如果该人能够到达所有点,即此调动方式成功。请写程序列出所有能够成功的调动情况。
...全文
439 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
isoftstonecom 2009-09-18
  • 打赏
  • 举报
回复
非常好
慢慢走luyie 2009-09-18
  • 打赏
  • 举报
回复
风暴很强烈
bingshanzhiling 2009-09-18
  • 打赏
  • 举报
回复
先标个记
xiaoyu821120 2009-09-16
  • 打赏
  • 举报
回复
刚我也写了个穷举,是382个

#include<iostream.h>
#include<string.h>
int a[12];//记录设置好的点数
int b[12];//记录用过的点数
int dfs(int pos,int level)
{
if(level==10)
{
for(int i=0;i<12;i++)
cout<<a[i]<<" ";
cout<<endl;
return 1;
}
int num=0;
int d;
for(int i=2;i<12;i++)
{
d = (pos+i)%12;
if(b[i]==0 && a[d]==0)
{
b[i] = 1;
a[pos] = i;
num+=dfs(d, level+1);
b[i] = 0;
a[pos] = 0;
}
}
return num;
}
int main()
{
memset(a, 0, sizeof(int)*12);
memset(b, 0, sizeof(int)*12);
a[0] = 1;
//a[6] = 12;
cout<<dfs(1,0)<<endl;
return 0;
}
showjim 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 sbwwkmyd 的回复:]
clocks(value, currentValue | (((ulong)nextValue) << shift), freeValue ^ (1 << (nextValue - 2)), nextShift, (errorValue >> nextValue) | (((errorValue | 1) << (12 - nextValue)) & 0xfff));[/Quote]
应改为
clocks(value, currentValue | (((ulong)nextValue) << nextShift), freeValue ^ (1 << (nextValue - 2)), nextShift, (errorValue >> nextValue) | (((errorValue | 1) << (12 - nextValue)) & 0xfff));
否则每个解值中会多出一个元素0值,当然也可以忽略掉它.
showjim 2009-09-16
  • 打赏
  • 举报
回复
如果第1个元素可以不为1,则解的个数为3856个.
        public static List<ulong> clocks()
{
List<ulong> value = new List<ulong>();
clocks(value, 0, 0x7ff, 40, 1 << 6);
return value;
}
private static void clocks(List<ulong> value, ulong currentValue, int freeValue, int shift, int errorValue)
{
for (int nextShift = shift - 4, nextValue = 1, nextFree = freeValue; nextFree != 0; nextValue++, nextFree >>= 1)
{
if ((nextFree & 1) != 0 && (errorValue & (1 << nextValue)) == 0)
{
if (nextShift == 0) value.Add(currentValue | (uint)nextValue);
else clocks(value, currentValue | (((ulong)nextValue) << nextShift), freeValue ^ (1 << (nextValue - 1)), nextShift, (errorValue >> nextValue) | (((errorValue | 1) << (12 - nextValue)) & 0xfff));
}
}
}
showjim 2009-09-16
  • 打赏
  • 举报
回复
我也写了一个,结果也是382个解(第1个值为1的解).
        public static List<ulong> clocks()
{
List<ulong> value = new List<ulong>();
clocks(value, 0, 0x3ff, 36, (1 << 5) | (1 << 11));
return value;
}
private static void clocks(List<ulong> value, ulong currentValue, int freeValue, int shift, int errorValue)
{
for (int nextShift = shift - 4, nextValue = 2, nextFree = freeValue; nextFree != 0; nextValue++, nextFree >>= 1)
{
if ((nextFree & 1) != 0 && (errorValue & (1 << nextValue)) == 0)
{
if (nextShift == 0) value.Add(currentValue | (uint)nextValue);
else clocks(value, currentValue | (((ulong)nextValue) << shift), freeValue ^ (1 << (nextValue - 2)), nextShift, (errorValue >> nextValue) | (((errorValue | 1) << (12 - nextValue)) & 0xfff));
}
}
}
showjim 2009-09-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 torey 的回复:]
引用 5 楼 sbwwkmyd 的回复:
引用 3 楼 litaoye 的回复:
想得不是很细,但感觉这题可能无解,用抽屉原则应该可以证明,大概思路就是11个mod 12各不相同的数,其和排列序列必然有mod 12 相同的两个数,这样就形成了死循环。

十二个也没有相同的数:
序 列01432567A98B
累加和0158A3942B76

怎么计算所有的呢?还是用穷举法吗?
[/Quote]
我的结果是基于假想:
我认为当n>1时,所有m=2n都存在解且符合下面的条件:
1.我认为累加和序列A1,A2,A3...Am满足条件当0=<x<n时|A(n+x+1)-A(n-x)|=n
当n为奇数时,就应该存在n-1组基本解,其它解都可以同基本解"无害交换位置"求得,如6有2组基本解
(014325,025314),(041352,052341)
交换位置:
a b c
-----
0 1 4
3 2 5
共(2^1)-1=1种交换
bc->025314
这样推出6有2*(2^1)=4种解。

2.我认为4n的解应该由2n可以的全解推导出全解,规则是2n的解做填充,填充规则是2n的基本解加2n,然后"无害交换位置"求全解,如12的解从6的解推导
014325 (014325)+6 => 01432567A98B
交换位置:
a bc d ef
---------
0 14 3 25
6 7A 9 8B
共(2^3)-1种交换,分别是d,c(e),cd(e),b(f),bd(f),bc(ef),bcd(ef),规则很明显就是bcd与def的对称位的全序列交换
d ->01492567A38B
ce ->01A38567492B
cde ->01A98567432B
bf ->07432B61A985
bdf ->07492B61A385
bcef ->07A38B614925
bcdef->07A98B614325
这样可以推出12有4*(2^3)=32种解,按照此方法推导24有32*(2^6)=2048种解。

注:现在还没有证明这就是全解,只是猜想。
绿色夹克衫 2009-09-15
  • 打赏
  • 举报
回复
写了个搜索算法,求出了3856个解,同楼上几位的答案都不一样,不知道有什么问题没有!


using System;

public class Example
{
private const int Length = 12;
private static bool[] NumFlag;
private static bool[] ModFlag;
private static int SolveCount = 0;

public static void Main()
{
NumFlag = new bool[Length];
ModFlag = new bool[Length];
Search(0, 0, 0, 0);
}

private static void Search(int index, int mod, long pValue, long pMod)
{
if (index == Length)
{
SolveCount++;
Console.WriteLine("{0} . {1:X} {2:X}", SolveCount, pValue, pMod);
return;
}

for (int i = 0; i < Length; i++)
{
if (!NumFlag[i])
{
int newMod = mod + i;

if (newMod >= Length)
newMod -= Length;

if (ModFlag[newMod])
continue;

ModFlag[newMod] = NumFlag[i] = true;
Search(index + 1, newMod, (pValue << 4) + i, (pMod << 4) + newMod);
ModFlag[newMod] = NumFlag[i] = false;
}
}
}
}
showjim 2009-09-15
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 fenix124 的回复:]
C/C++ code
#include"stdio.h"int position[12];int used[13];int oknum;int totalcount;void GetSequence(int prevpos,int curpos)
{int i;int temp;if(oknum==12)
{for(i=0;i<12;i++)
{// printf("¡­
[/Quote]
里面有很多重复的解,借你的程序改了一下,得到382个唯一解,我前面的假想是错误码的,只能得到很小一部分解.
fenix124 2009-09-15
  • 打赏
  • 举报
回复

#include "stdio.h"

int position[12];
int used[13];
int oknum;
int totalcount;

void GetSequence(int prevpos,int curpos)
{
int i;
int temp;
if(oknum == 12)
{
for(i = 0;i < 12;i++)
{
// printf("%d ",position[i]);
}
// printf("\n");
totalcount++;
return;
}
for(i = 1;i <= 12;i++)
{
if(!used[i] && position[(curpos+i)%12] == 0)
{
position[curpos] = i;
used[i] = 1;
oknum++;
GetSequence(curpos,(curpos+i)%12);
position[curpos] = 0;
used[i] = 0;
oknum--;
}
}
}

int main()
{
used[1] = 1;
oknum = 1;
position[1] = 1;
GetSequence(1,2);
printf("totalcount = %d",totalcount);
while(1);
return 0;
}
fenix124 2009-09-15
  • 打赏
  • 举报
回复
共有4202种,如果不作输出,速度大概1秒。
#include "stdio.h"

int position[12];
int used[13];
int oknum;
int totalcount;

void GetSequence(int prevpos,int curpos)
{
int i;
int temp;
if(oknum == 12)
{
for(i = 0;i < 12;i++)
{
// printf("%d ",position[i]);
}
// printf("\n");
totalcount++;
return;
}
for(i = 1;i <= 12;i++)
{
if(!used[i] && position[(curpos+i)%12] == 0)
{
position[curpos] = i;
used[i] = 1;
oknum++;
GetSequence(curpos,(curpos+i)%12);
position[curpos] = 0;
used[i] = 0;
oknum--;
}
}
}

int main()
{
used[1] = 1;
oknum = 1;
position[1] = 1;
GetSequence(1,2);
printf("totalcount = %d",totalcount);
while(1);
return 0;
}
xiaoxiassk 2009-09-15
  • 打赏
  • 举报
回复
很有意思!一会研究一下!
fenix124 2009-09-15
  • 打赏
  • 举报
回复
写个递归来枚举即可.
绿色夹克衫 2009-09-14
  • 打赏
  • 举报
回复
LS确实很棒!
我考虑不细致,希望没有误导大家,不好意思,这道题是有解的。

[Quote=引用 6 楼 ahjoe 的回复:]
楼上的很棒
[/Quote]
super_chris 2009-09-14
  • 打赏
  • 举报
回复
因为只要在走全12个点之前到达一个点两次 那就肯定不能走全 因为肯定会陷入循环 所以要完成这个任务 肯定是走12步 不多不少 而且这12步的步长分别是1,2,3...,12 所以一共走(1+2+3+……+12)=78步。也就是绕表不超过7圈,所以若将表上的点排列好并选取了起点后 可以构造一个将表盘从起点开始循环7次的列表 实际上 这个数组的长度可以截断为79 因为一共走78步 这样每次只要路过了曾经路过的点(实际是路过了和曾路过的点数相同的点)这次尝试就算失败了
一共需要尝试11!次 因为第一个点肯定是1 所以只需排列剩下11个点
不知道11!次能不能承受。。。
哦 对了 由于如果路过12点 那么下一步的步长是12 将又回到12 所以12必须最后路过 也就是第79个点是12 所以在表盘上12应该和1相距6 (79-1)%12=6
这样就还剩下10!种情况了
10!大概在3620000 感觉还可以接受吧。。。
morilasi 2009-09-14
  • 打赏
  • 举报
回复
有意思,MARK一下
super_chris 2009-09-14
  • 打赏
  • 举报
回复
这个调动是什么意思啊?重新排列表盘上的12个数字?
xiaoyu821120 2009-09-14
  • 打赏
  • 举报
回复
如果我没有理解错误的话,我觉得0的位置应该是在1的对点位置,因为1+2+3+...+11=66,66%12=6
Torey 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sbwwkmyd 的回复:]
引用 3 楼 litaoye 的回复:
想得不是很细,但感觉这题可能无解,用抽屉原则应该可以证明,大概思路就是11个mod 12各不相同的数,其和排列序列必然有mod 12 相同的两个数,这样就形成了死循环。

十二个也没有相同的数:
序  列01432567A98B
累加和0158A3942B76
[/Quote]
怎么计算所有的呢?还是用穷举法吗?
加载更多回复(8)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧