约瑟夫环 (josephus problem )问题,有公式 可以直接套用
我使用暴力破解方法求解(用时3秒多)。
代码如下:
/* zoj 1088 System Overload */ #include <stdio.h> #include <string.h> #define MAXBUILDING 150 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 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; else return (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 150 int 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; }