竞赛题目选讲
1,刽子手游戏:
在博客上一找,基本都是混子把书上的代码复制了一遍;
,希望博客可以管理一下这些人,删除不用心的博客
思路:
1.输入2个字符串
2.每一个S2里面在s1里面找找看有没有一样的,没有chance就扣去一
3。因为猜过的数字不能再猜,用一个数组记录猜过的数字看看有没有重复
代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string m,n;
int count = 0;
while(cin>>count>>m>>n&&count != -1)
{
int chance=7,left=m.size();//chance 是能猜的机会,left是能猜的位置
for(int i=0;i<n.size();++i)
{
int ok=0;//一开始标记没猜对
for(int j=0;j<m.size();++j)
{
if(n[i]==m[j])
{
m[j]=' '; //在这个是精华
left--;
ok=1;
}//猜对了位置扣去一 ok=1;
}
if(ok==0) chance--;//没猜对减去一次机会
}
if(left <= 0) cout<<"you win"<<endl;
else if(chance <= 0) cout<<"you lose"<<endl;
else cout<<"you chickened out"<<endl;
}
}
核心:
int ok=0;//一开始标记没猜对
if(ok==0) chance--;//没猜对减去一次机会
这个写法就i是一个模板:
如果ok=0没猜对,标记没猜对的话机会就少了一次;
for(int j=0;j<m.size();++j)
{
if(n[i]==m[j])
{
m[j]=' '; //在这个是精华
left--;
ok=1;
}//猜对了位置扣去一 ok=1;
}
n[i]==m[j] 如果猜对了,要猜的位置减去1,ok=1;
还有一个注意点:
猜过的数字,不能再猜;
有2方法:
a.把每次字符存下来,然后一次for循环,找到的话就chance;
b.把猜对的字符在s1里面全部改为空格
有2种情况
a.把猜对的元素全部改为“ ”空格,这样猜对的话就可以把所有猜过而且猜对的元素都改为空格;这样后面再输入这个字符的话就匹配不上去,相当于错了一次;
b.猜的没有在s1里面;
这样没猜对,和猜过都要扣去一次机会,没有必要
***技巧:如果一个东西不能重复就把之前猜过的一次,就把全部的元素替换,这样后续就匹配不到
2.
救济金发放;
m个人站在一个圈,官员a数k个停下来,官员b数m个停下来,选中的官员离开
官员a逆时针数,官员b顺时针数
思路:
/
1.输入n,k,m
2.模拟每次的操作,如果还有剩下就操作
3.如果遇到空格,遇到第一个非空格就才t–;
4.如果是最后一个的话就不用输出“,”
*/
#include <iostream>
using namespace std;
int a[10010],m,n,k;
int go(int p,int d,int t)
{
while(t--)
{
do
{
p=(p+d+n-1)%n+1;
}while(a[p]==0);
}
return p;
}
int main()
{
cin>>n>>k>>m;
int left=n;
int p1=n,p2=1;
for(int i=1;i<=n;++i) a[i]=i;
while(left)//还剩下一些人
{
p1=go(p1,1,k);
p2=go(p2,-1,m);//p1,p2是要出队的人
cout<<p1<<" ";//输出p1是谁
left--;//出队一个人
if(p2!=p1)
{
cout<<p2;
left--;//如果p2和p1不是一个人继续出队
}
a[p1]=a[p2]=0;
if(left) cout<<",";//还有人的话就要输出,;
}
cout<<endl;
return 0;
}
核心:
1.利用一个变量来标记是否要输出逗号:
这个技巧可以用来标记是否要输出空格;
if(left) cout<<",";
如果不是最后一个就输出逗号;
扩展:
**质数的分解。**题目私信我;
2.数过的元素,数过的数组改为空格
这个技巧和上面那一个技巧异曲同工之妙,,有的时候为了不去操作数组,改变数组就用这个技巧来防止重复计数;
a[p1]=a[p2]=0;
数过的人把它改为空格,这样后面数到的话就跳过;
3.移动函数:
int go(int p,int d,int t)
{
while(t--)
{
do
{
p=(p+d+n-1)%n+1;
}while(a[p]==0);
}
return p;
}
while(要需要移动的话)
{
那就移动到第一个非0的数字,因为0已经动过了,不能算;
}
p=(p+d+n-1)%n;
这个是根据公式推演出来
一个是正向
p是当前位置,d是移动几步,n可以叫做数组偏移量,如果逆时针没有加上这个的话会出现负数%n是防止正的时候超过数组;
扩展约瑟夫环问题
#include <iostream>
using namespace std;
int a[10010],m,n,k;
int go(int p,int t)
{
do
{
p=(p+t+n)%n;
}while(a[p]==0);
return p;
}
int main()
{
cin>>n>>k;
int left=n;
int p1=1;
for(int i=1;i<=n;++i) a[i]=i;
while(left)
{
p1=go(p1,k);
cout<<p1<<" ";
left--;//出队一个人
a[p1]=0;
if(left!=1) cout<<",";//还有人的话就要输出,;
}
cout<<endl;
return 0;
}
思路:
每次移动步数,然后出队,把出队的地方改为0;
每次移动到第一个非0的数字;
模板总结:
int go(int p,int t)
{
do
{
p=(p+t+n)%n;
}while(a[p]==0);
return p;
}
while(a[p]==0)/如果是0就跳过,找到第一个非0就输出;