标签:zoj zoj1088 acm 算法 josephus
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">zoj 1088题目题目大意是,对n栋楼停电,先停第一栋,再隔m栋停一栋。数到最后一栋后从头循环计数,已经断电的不参与计数。要选取适当的m,使得即使其他楼都没电了,但第二栋楼仍然有电。 </span>
如果将该题视为普通的模拟算法,其时间复杂度将高达O(m*n)。由于题目给了很充足的时间和很小的m、n范围,一般的模拟算法即可完成。但有没有更高效的算法呢。
常见的优化方法是每断掉一栋楼的电,问题规模就减一,这样时间复杂度就降到了O(n)。 下面转帖内容:
一般使用这种方法的C/C++时间消耗在20ms以上,占用内存大概在272kB左右。
还可以使用j(2^n)=1的特性来优化计算,即对于原问题,对于n=2^p的情况,直接输出1而避免计算。 最后消耗时间0,空间168kb(c/c++消耗等同)。
下面贴出本人的原代码。这个算法已经非常接近最佳排行160KB。但是不知道如何继续降低空间消耗。 希望在学完COM一书后能有优化。
#include<cstdio> using namespace std; //Arthur::Xiaoqiang AN int joseph(int k,int b) { int res=0; for(int i=2;i<=k;++i) res=(res+b)%i; return res; } int main() { int n,t; while(scanf("%d",&n),n) { t=n-1; if(t==2||t==4||t==8||t==16||t==32||t==64||t==128) { printf("2\n"); continue; } else { for(int m=3;;++m) if(joseph(t,m)==0) { printf("%d\n",m); break; } } } }
如果直接模拟,然后输出所有结果到数组,最后备查的话,也可以将时间降为0,但空间消耗可能会大于168KB。 本人用自己前面的代码,将结果输出到文本,并重新查表输出的代码如下:
(为vim打个广告, 将输出结果改造为数组值的过程全部使用vim实现,最多只需要十次以内的操作,一分钟就能搞定,强烈推荐使用vim编程)。
#include<stdio.h> int main() { int m[153]; m[0]=-1; m[1]=-1; m[2]=-1; m[3]=2; m[4]=5; m[5]=2; m[6]=4; m[7]=3; m[8]=11; m[9]=2; m[10]=3; m[11]=8; m[12]=16; m[13]=4; m[14]=21; m[15]=6; m[16]=5; m[17]=2; m[18]=11; m[19]=20; m[20]=34; m[21]=8; m[22]=15; m[23]=10; m[24]=7; m[25]=13; m[26]=11; m[27]=13; m[28]=45; m[29]=18; m[30]=23; m[31]=8; m[32]=3; m[33]=2; m[34]=25; m[35]=75; m[36]=42; m[37]=13; m[38]=5; m[39]=23; m[40]=13; m[41]=50; m[42]=16; m[43]=18; m[44]=89; m[45]=38; m[46]=8; m[47]=39; m[48]=30; m[49]=29; m[50]=38; m[51]=7; m[52]=45; m[53]=23; m[54]=137; m[55]=46; m[56]=63; m[57]=17; m[58]=48; m[59]=5; m[60]=46; m[61]=34; m[62]=140; m[63]=33; m[64]=39; m[65]=2; m[66]=28; m[67]=29; m[68]=79; m[69]=33; m[70]=48; m[71]=3; m[72]=10; m[73]=46; m[74]=120; m[75]=6; m[76]=37; m[77]=17; m[78]=8; m[79]=44; m[80]=15; m[81]=160; m[82]=20; m[83]=35; m[84]=144; m[85]=104; m[86]=179; m[87]=153; m[88]=24; m[89]=8; m[90]=265; m[91]=19; m[92]=9; m[93]=62; m[94]=7; m[95]=139; m[96]=19; m[97]=44; m[98]=93; m[99]=182; m[100]=27; m[101]=158; m[102]=185; m[103]=193; m[104]=17; m[105]=82; m[106]=3; m[107]=11; m[108]=43; m[109]=55; m[110]=21; m[111]=41; m[112]=146; m[113]=29; m[114]=80; m[115]=59; m[116]=8; m[117]=29; m[118]=66; m[119]=19; m[120]=160; m[121]=59; m[122]=28; m[123]=129; m[124]=127; m[125]=120; m[126]=72; m[127]=45; m[128]=157; m[129]=2; m[130]=63; m[131]=127; m[132]=81; m[133]=318; m[134]=513; m[135]=98; m[136]=28; m[137]=32; m[138]=231; m[139]=236; m[140]=411; m[141]=26; m[142]=45; m[143]=5; m[144]=303; m[145]=228; m[146]=66; m[147]=9; m[148]=205; m[149]=65; m[150]=39; m[151]=16; int n; while(scanf("%d",&n),n) { printf("%d\n",m[n]); } return 0; }
标签:zoj zoj1088 acm 算法 josephus
原文地址:http://blog.csdn.net/al5hn/article/details/43021301