Joseph
Time Limit: 1000MS Memory Limit: 10000K
Description
The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved.
Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.Input
The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.
Output
The output file will consist of separate lines containing m corresponding to k in the input file.
Sample Input
3
4
0Sample Output
5
30
最终还是过了,真的吐血了,我用链表模拟去从1跑到13也就124ms为啥提交上去还是超时了,非常疑惑,然后参考了大佬的代码,先把1到13的值求出来再一个个输出值就过了,,,真的吐血了,,,~~~
剪枝方法:
1.只有当m为m%(k+1) == 0或者m%(k+2) == 0时才有效,因为当只剩最后两个坏人的时候,若先死的是排名在前面的坏人,那么下一次一定是 k+2的倍数才能数到下一个坏人,若先死的是排名在后面的坏人,那么下一次一定是 k+1 的倍速才能数到下一个坏人。
2.模拟过程一定要取模后再去模拟。
3.首次计算的值一定是k+1,小于等于k的值都不行。
4.最最最重要的,先把1-13的值都求出来后再去根据输入的n来输出值!!!!!!!!!!!!
#include <iostream>
#include <algorithm>
using namespace std;
bool isSuccess;
int k;
struct LinkTable
{
int _pos;
LinkTable* next;
LinkTable(int pos) { this->_pos = pos; };
};
LinkTable* _linkTable;
LinkTable* _startTable;
int totalSize = 0;
void addLinkTable(int pos) {
if (_linkTable == NULL) {
_linkTable = new LinkTable(pos);
_linkTable->next = _linkTable;
_startTable = _linkTable;
}
else {
LinkTable* newLinkTable = new LinkTable(pos);
newLinkTable->next = _linkTable->next;
_linkTable->next = newLinkTable;
_linkTable = newLinkTable;
}
}
int start(int last, int num, LinkTable* startPos) {
if (last <= 0) {
isSuccess = true;
return 1;
}
int useNum = (num - 1) % totalSize + 1;
int pos;
LinkTable* lastPos = startPos;
if (useNum == 1) {
useNum += totalSize;
}
while (useNum != 0) {
useNum--;
if (useNum == 1) {
lastPos = startPos;
}
if (useNum != 0) {
startPos = startPos->next;
}
}
pos = startPos->_pos;
if (pos <= k) {
return 0;
}
else
{
lastPos->next = startPos->next;
totalSize--;
start(last - 1, num, startPos->next);
}
lastPos->next = startPos;
}
int main() {
int allResult[14];
for (int n = 1; n < 14; n++) {
k = n;
_linkTable = NULL;
for (int i = 1; i <= n * 2; i++) {
addLinkTable(i);
}
isSuccess = false;
int num = n;
while (!isSuccess) {
num++;
if (!(num % (n + 1) == 0 || num % (n + 1) == 1)) {
continue;
}
totalSize = n * 2;
start(n, num, _startTable);
}
allResult[n] = num;
}
int n;
while (cin>>n && n)
{
cout << allResult[n] << endl;
}
return 0;
}
以下是通过的方法,没用链表,直接用数组去循环的。
#include <iostream>
using namespace std;
int start(int last, int num) {
int i = 0;
int j = 0;
for (i = 0; i < last; i++) {
j = (j + num - 1) % (2 * last - i);
if (j < last) {
return 0;
}
}
return 1;
}
int main() {
int allResult[14];
for (int i = 1; i < 14; i++) {
int num = i;
while (true) {
num++;
if (!(num % (i + 1) == 0 || num % (i + 1) == 1)) {
continue;
}
int result = start(i, num);
if (result) {
break;
}
}
allResult[i] = num;
}
int n;
while (cin>>n && n)
{
cout << allResult[n] << endl;
}
return 0;
}