P1145 约瑟夫

题目描述

n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人。现在有一圈人,k个好人站在一起,k个坏人站在一起。从第一个好人开始数数。你要确定一个最小的m,使得在第一个好人被杀死前,k个坏人先被杀死。

感谢yh大神指出样例数据的错误。

输入输出格式

输入格式:

 

一个k,0<k<14

 

输出格式:

 

一个m

 

输入输出样例

输入样例#1: 复制
3
输出样例#1: 复制
5
输入样例#2: 复制
4
输出样例#2: 复制
30

说明

0<k<14

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k;
int vis[29];
bool dfs(int kk){
    int sum=0,s=0;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++){
        if(sum==k)    break;
        if(!vis[i])    s++;
        if(s==kk){
            s=0;
            if(i<=k&&sum<k)    return    false;
            else{
                if(i>k)    sum++;
                vis[i]=1;
            } 
        }
        if(i==n)    i=0;
    }
    return true;
}
int main(){
    scanf("%d",&k);n=k*2;
    for(int i=1;i;i++)
        if(dfs(i)){
            cout<<i;
            break;
        }
}
暴力代码

思路:剪枝后的dfs

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,s;
int vis[300];
bool judge(int p,int m){
    int ans=(s+m)%p;
    if(ans>=k){ s=ans;return 0; }    
    else return 1;
}
bool dfs(int p){
    s=0;
    for(int i=0;i<k;i++)
        if(judge(2*k-i,p))
            return false;
    return true;
}
int main(){
    scanf("%d",&k);n=k*2;
    for(int i=1;i;i++)
        if(dfs(i)){
            cout<<i+1;
            break;
        }
}
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/7899302.html