约瑟夫环 (josephus problem )问题,有公式 可以直接套用
我使用暴力破解方法求解(用时3秒多)。
代码如下:
/* zoj 1088 System Overload */ #include <stdio.h> #include <string.h>#define MAXBUILDING 150int minStepNum(int totalBuilding, int lastNum);int main(void) {int n;/* int minStepTab[MAXBUILDING];int i;for(i = 3; i < MAXBUILDING; i++)minStepTab[i] = minStepNum(i,2);*/while(scanf("%d", &n) == 1 && n != 0)/* printf("%d\n", minStepTab[n]);*/printf("%d\n",minStepNum(n,2));return 0;} int minStepNum(int totalBuilding, int lastNum) {int minStep = 2;int count,i,flag;int isCutOff[MAXBUILDING];int buildings[MAXBUILDING];for(i = 0; i < totalBuilding; i++)buildings[i] = i+1;while(1){memset(isCutOff,0,sizeof(isCutOff));isCutOff[0] = 1;flag = 0;for(i = count = 0; count < minStep * (totalBuilding-2);i = (i+1)%totalBuilding)if(isCutOff[i] == 0){count++;if(count % minStep == 0 && buildings[i] == lastNum){flag = 1;break;}else if(count % minStep == 0)isCutOff[i] = 1;}if(count == minStep*(totalBuilding-2) && !flag)for(i = 0; i < totalBuilding; i++)if(isCutOff[i] == 0)return minStep;minStep++;}return 0; }
直接套用公式的代码(15ms):
#include <stdio.h>int Josephus(int n, int m) {if(n == 1)return 0;elsereturn (Josephus(n-1,m)+m)%n; } int main(void) {int n;int i;while(scanf("%d", &n) == 1 && n != 0){for(i = 2;; i++)if(Josephus(n-1,i) == 0){printf("%d\n",i);break;}}return 0; }
起初我使用最原始的暴力破解法(未使用任何优化),结果超时了(可能需要15秒左右,超出了规定的10秒限制)
产生超时结果对应代码:
/* zoj 1088 System Overload */ #include <stdio.h> #include <string.h>#define MAXBUILDING 150int lastNumber(int totalBuilding, int stepNum); int minStepNum(int totalBuilding, int lastNum);int main(void) {int n;int minStepTab[MAXBUILDING];int i;for(i = 3; i < MAXBUILDING; i++)minStepTab[i] = minStepNum(i,2);while(scanf("%d", &n) == 1 && n != 0)printf("%d\n", minStepTab[n]);/* printf("%d\n",minStepNum(n,2));*/return 0; } int minStepNum(int totalBuilding, int lastNum) {int i;for(i = 2; lastNumber(totalBuilding,i) != lastNum; i++) ;return i; } int lastNumber(int totalBuilding, int stepNum) {int building[MAXBUILDING],isCutOff[MAXBUILDING];int i,count;memset(isCutOff,0,sizeof(isCutOff));for(i = 0; i < totalBuilding; i++)building[i] = i+1;isCutOff[i=0] = 1;/* count = 0;*/for(count = 0;count < stepNum * (totalBuilding-2); i = (i+1)%totalBuilding)if(isCutOff[i] == 0){count++;if(count % stepNum == 0)isCutOff[i] = 1;}for(i = 0; i < totalBuilding; i++)if(isCutOff[i] == 0)return building[i];return 0; }