POJ1012 Joseph

题目来源:http://poj.org/problem?id=1012

题目大意:求解约瑟夫环问题(1-n个人站成一个圈,选择一个数k,首先从1开始数,第k个人被处决,然后再从下一个人开始数,第k个人被处决,如此循环)。假设环中由k个好人和k个坏人,前k为好人,后k为坏人。找出最小的m使得在有好人被处决前所有坏人都被处决掉。

输入:每行1个k(0<k<14),由0作为结束。

输出:对于每个k输出最小的m。


Sample Input

3
4
0

Sample Output

5
30

直接暴力做TLE了,看到Discuss里面说测试数据里有重复,每计算一个k将结果的m保存,下一次求k时只要查表即可。

 1 //////////////////////////////////////////////////////////////////////////
 2 //        POJ1012 Joseph
 3 //        Memory: 248K        Time: 235MS
 4 //        Language: C++        Result: Accepted
 5 //////////////////////////////////////////////////////////////////////////
 6 
 7 #include <iostream> 
 8 
 9 using namespace std;
10 
11 int result[13];
12 int k, m;
13 
14 //检验m是不是k的解
15 bool isSolution(int k, int m) {
16     int lastKilled = 0;
17     for (int i = 0; i < k; i++) {
18         int killed = (lastKilled + m - 1) % (2 * k - i);
19         if (killed < k) {
20             return false;
21         } else {
22             lastKilled = killed;
23         }
24     }
25     result[k-1] = m;
26     return true;
27 }
28 
29 int main() {
30     while (true) {
31         cin >> k;
32         if (k == 0)  {
33             break;
34         }
35         //查表
36         if (result[k - 1] != 0) {
37             cout << result[k - 1] << endl;
38             continue;
39         }
40         int m = k + 1;
41         while (true) {
42             if (isSolution(k, m)) {
43                 cout << m << endl;
44                 break;
45             } else {
46                 m++;
47             }
48         }
49     }
50     return 0;
51 } 
View Code

由于k的取值范围很小,更加水的方法是在本地把所有可能的输出求出来,然后直接查表输出...

 1 //////////////////////////////////////////////////////////////////////////
 2 //        POJ1012 Joseph
 3 //        Memory: 164K        Time: 0MS
 4 //        Language: C++        Result: Accepted
 5 //////////////////////////////////////////////////////////////////////////
 6 
 7 #include <stdio.h>
 8 int main() {
 9     int k;
10     for(;;) {
11         scanf("%d",&k);
12         if (!k)
13             break;
14         switch (k) {
15         case 1:printf("2\n");break;
16         case 2:printf("7\n");break;
17         case 3:printf("5\n");break;
18         case 4:printf("30\n");break;
19         case 5:printf("169\n");break;
20         case 6:printf("441\n");break;
21         case 7:printf("1872\n");break;
22         case 8:printf("7632\n");break;
23         case 9:printf("1740\n");break;
24         case 10:printf("93313\n");break;
25         case 11:printf("459901\n");break;
26         case 12:printf("1358657\n");break;
27         case 13:printf("2504881\n");break;
28         }
29     }
30     return 0;
31 }
View Code
posted @ 2013-07-31 00:07  小菜刷题史  阅读(395)  评论(0编辑  收藏  举报