P1145 约瑟夫
题目描述
n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人。现在有一圈人,k个好人站在一起,k个坏人站在一起。从第一个好人开始数数。你要确定一个最小的m,使得在第一个好人被杀死前,k个坏人先被杀死。
感谢yh大神指出样例数据的错误。
输入输出格式
输入格式:
一个k,0<k<14
输出格式:
一个m
输入输出样例
说明
0<k<14
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; } }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。