20180318CSP比赛
一共五道题
1.跳一跳
2.小球碰撞
3.指令匹配?
4.下棋
5.二次查找?
我只做了1,2,4 三个题 不知道结果如何。记录一下~
跳一跳
题目描述:输入一串数字 1代表跳上了但不在中间 2代表跳在中间 0代表没跳上下一个 计算本局跳一跳成绩
输入样例:1 1 2 2 2 1 1 2 2 0
输出:22 (1+1+2+4+6+1+1+2+4)
#include<iostream> using namespace std; int main(){ int a[30]; int score=0; int figure=0,num=0; int flag=0; for(int i=0;i<30;i++){ cin>>a[i]; num++; if(a[i]==0) break; } for(int j=0;j<num;j++){ if(a[j]==1) { flag=0; figure=1; score+=figure; } else if (a[j]==2 ) { flag++; figure=2*flag; score+=figure; } } cout<<score; return 0; }
出现的问题:刚开始输入一串数字时,我的方法是
for(int i=0;a[i]!=0;i++){
cin>>a[i];
num++;
} 但是一直不能输出正确的结果2333 在考试的电脑上输入 1 1 2 2 2 11 2 2 0 但是得到的数组却是 1 1 2 2 2 1 1 (2 2 丢失) 在我自己的电脑上只得到了1
当然了,这种写法是错误的。因为a[i]的值是后来才输入的 所以判断是否a[i]!=0的时候a[i[还是未知的...考试的时候没有反应过来。其实用while循环也可以的。
程序的思路是 用figure记录这次跳的分数,score是总分。flag的作用是记录是否连续跳中间,在中间连续跳了几次。
小球碰撞
题目描述:数轴上有一个长为L的绳子,左端点在原点,右端点是L。L是一个偶数,绳子上有n个小球,它们的初始位置也都是偶数,开始时他们都以1(长度单位/时间单位)的速度向右匀速运动,到达两端点就按原速率反向运动,小球之间碰撞时也按原速率反向运动。 求t时刻各个小球的位置。
分析与提示:L是偶数,小球的初始坐标为偶数都是为了简化题的难度。提示中说小球碰撞的时间都是整数的时间,也不存在三个小球相互碰撞的情况。
思路:既然小球碰撞的时间是整数的时间,那就时间每增一,计算每个小球的位置和方向。满足碰撞条件就改变其方向。
#include<iostream> using namespace std; int main(){ int n,l,t; cin>>n>>l>>t; int *right=new int[n]; int *now=new int[n]; int *first=new int [n]; for(int i=0;i<n;i++){ cin>>first[i]; right[i]=1; } for(int k=0;k<t;k++){ for(int j=0;j<n;j++){ first[j]=(first[j]+1)%(2*l); if(first[j]<l){ now[j]=first[j]; right[j]=1; } else if(first[j]>=l && first[j]<2*l){ now[j]=2*l-first[j]; right[j]=0; } } for(int i1=0;i1<n;i1++){ for(int j1=i1+1;j1<n;j1++){ if(now[i1]==now[j1] && right[i1]+right[j1]==1 ){ int t=first[i1]; first[i1]=first[j1]; first[j1]=t; } } } } for(int m=0;m<n;m++){ cout<<now[m]<<" "; } delete []now; delete []right; delete []first; return 0; }
我的思路是用first数组记录每个小球的相对移动量(mod 2*L),用now数组计算每个小球的位/置坐标。因为小球可以有两个方向的移动,那么first数组某元素的值如果在0-L之间,就说明此小球正在向右移动,如果在L-2L之间就说明在向左移动。
我需要先解释一下first数组的含义。假设小球到右端点不反弹,保持向右的匀速直线运动。那么当它距离原点为2倍L的时候,实际上这时它正好回到了原点。相当于我们把小球折回的这段路程展开了。而它距离原点超过2倍L的时候,它又向右匀速运动了。因此所有的小球的运动都可以被分成两个部分:距离原点0 -> L:向右匀速 ; 距离原点 L -> 0:向左匀速。first数组中元素的值其实就是一去一回中小球离原点的路程(不是位移)。因为如果first值等于2L,就相当于在原点,接下来都是重复的过程。因此first数组值的取值范围就是0-2L (左闭右开区间) 即[0, 2L)。 值为0到L的小球向右匀速运动,值为L到2L的小球向左匀速运动。端点值需要特别注意 0:左端点 速度向右 L:右端点 速度向左
right数组记录每个小球的方向。值为0 方向向左,值为1 方向向右。(后来我发现first和right作用是相同的,要一个就好了)
因为题干说最开始所有的小球都向右匀速。因此把right数组每个元素值都设为1。外层的for循环是对时间的循环(时间每次增加1,看所有小球的位置),内层的for循环是对小球的遍历,看每个小球的位置。遍历得到每个小球的位置,就可以找是否有小球位置相同速度方向相反了(判断速度方向是否相反,可以把right[r1]+right[j1]==1改成first[r1]+first[j1]==2*L),这是发生碰撞的充要条件。碰撞后两球交换速度。
最开始first[j]=(first[j]+1)%(2*l);这步我开始写错了 我是这样写的:if(right[j]==1) first[j]=(first+1)%(2*l) ;else first[j]=(first-1)%(2*l) ; 注意是一秒一秒看的 所以是加减1而不是加减k(严格的说是加减1乘以速度 ,但速度也为1)这样看起来好像很对,但其实是我把first数组和now数组混淆了。如果按错误的写法,first值永远不能达到L-2L 。
这个算法就是在模拟整个过程。
下棋
题目描述:3*3的棋盘上,Alice和Bob一起下棋。Alice先下x,Bob后下o。谁先脸上三个谁赢。分数的设定是:如果Alice赢了,分数是棋盘上空格数加一;如果Bob赢了,分数是负的(棋盘上空格数加一)。如果棋下满了谁也没连上三个,就平局,分数为0。输入玩的局数以及每局当前的状态,计算当前状态的分数。(两个人都是按照最优的方案下棋)
输入:n局棋 和每局棋的状态。0代表空,1代表Alice下的x,2代表Bob下的o
输出:n局棋当前状态下的得分
输入样例:
3
1 2 1
2 1 2
0 0 0
2 1 1
0 2 1
0 0 2
0 0 0
0 0 0
0 0 0
输出:
3
-4
0
注意点:如果当前状态下谁都没连上三个棋,但是空的位置上恰好有一个位置能让下一个出棋的人连上三个,由于两个人都是按照最优的方案下棋,当前成绩就是这个人赢。
对于3*3棋盘,以a[9]表示,能连上三个的下标有:012,036,048,147,246,258,345,678。因此我暴力枚举......
#include<iostream> using namespace std; int kong(int *a){ int count=0; for(int k=0;k<9;k++){ if(a[k]==0) count++; } return count; } int shewin(int *a){ int countA=0,countB=0; for(int m=0;m<9;m++){ if(a[m]==1) countA++; else if(a[m]==2) countB++; } int flag=0; if(countA==countB&&countA==0)return flag; if(a[0]==a[1]&&a[1]==a[2]&&a[0]!=0){ if(a[0]==1) flag=1; else flag=-1; return flag; } else if(a[0]==a[3]&&a[3]==a[6]&& a[0]!=0){ if(a[0]==1) flag=1; else flag=-1; return flag; } else if(a[0]==a[4]&&a[4]==a[8]&& a[0]!=0){ if(a[0]==1) flag=1; else flag=-1; return flag; } else if(a[1]==a[4]&&a[4]==a[7]&& a[1]!=0){ if(a[1]==1) flag=1; else flag=-1; return flag; } else if(a[2]==a[4]&&a[4]==a[6]&& a[4]!=0){ if(a[2]==1) flag=1; else flag=-1; return flag; } else if(a[2]==a[5]&&a[5]==a[8]&& a[2]!=0){ if(a[2]==1) flag=1; else flag=-1; return flag; } else if(a[4]==a[3]&&a[3]==a[5]&& a[3]!=0){ if(a[3]==1) flag=1; else flag=-1; return flag; } else if(a[6]==a[7]&&a[8]==a[6]&& a[7]!=0){ if(a[7]==1) flag=1; else flag=-1; return flag; } if(countA>countB){ if(a[0]==a[1]&&a[0]==2&&a[2]==0){ a[2]=2;flag=-1;return flag; } else if(a[0]==a[2]&&a[0]==2&&a[1]==0){ a[1]=2;flag=-1;return flag; } else if(a[2]==a[1]&&a[1]==2&&a[0]==0){ a[0]=2;flag=-1;return flag; } else if(a[0]==a[3]&&a[0]==2&&a[6]==0){ a[6]=2;flag=-1;return flag; }else if(a[0]==a[6]&&a[0]==2&&a[3]==0){ a[3]=2;flag=-1;return flag; }else if(a[3]==a[6]&&a[3]==2&&a[0]==0){ a[0]=2;flag=-1;return flag; }else if(a[0]==a[4]&&a[0]==2&&a[8]==0){ a[8]=2;flag=-1;return flag; }else if(a[0]==a[8]&&a[0]==2&&a[4]==0){ a[4]=2;flag=-1;return flag; }else if(a[8]==a[4]&&a[4]==2&&a[0]==0){ a[0]=2;flag=-1;return flag; }else if(a[4]==a[1]&&a[4]==2&&a[7]==0){ a[7]=2;flag=-1;return flag; }else if(a[1]==a[7]&&a[1]==2&&a[4]==0){ a[4]=2;flag=-1;return flag; }else if(a[4]==a[7]&&a[4]==2&&a[1]==0){ a[1]=2;flag=-1;return flag; }else if(a[2]==a[5]&&a[2]==2&&a[8]==0){ a[8]=2;flag=-1;return flag; }else if(a[8]==a[5]&&a[5]==2&&a[2]==0){ a[2]=2;flag=-1;return flag; }else if(a[2]==a[8]&&a[2]==2&&a[5]==0){ a[5]=2;flag=-1;return flag; }else if(a[2]==a[4]&&a[2]==2&&a[6]==0){ a[6]=2;flag=-1;return flag; }else if(a[2]==a[6]&&a[2]==2&&a[4]==0){ a[4]=2;flag=-1;return flag; }else if(a[4]==a[6]&&a[4]==2&&a[2]==0){ a[2]=2;flag=-1;return flag; }else if(a[3]==a[4]&&a[3]==2&&a[5]==0){ a[5]=2;flag=-1;return flag; }else if(a[4]==a[5]&&a[4]==2&&a[3]==0){ a[3]=2;flag=-1;return flag; }else if(a[3]==a[5]&&a[3]==2&&a[4]==0){ a[4]=2;flag=-1;return flag; }else if(a[6]==a[7]&&a[6]==2&&a[8]==0){ a[8]=2;flag=-1;return flag; }else if(a[7]==a[8]&&a[7]==2&&a[6]==0){ a[6]=2;flag=-1;return flag; }else if(a[6]==a[8]&&a[6]==2&&a[7]==0){ a[7]=2;flag=-1;return flag; } }else if(countA==countB){ if(a[0]==a[1]&&a[0]==1&&a[2]==0){ a[2]=1;flag=1;return flag; } else if(a[0]==a[2]&&a[0]==1&&a[1]==0){ a[1]=1;flag=1;return flag; } else if(a[2]==a[1]&&a[1]==1&&a[0]==0){ a[0]=1;flag=1;return flag; } else if(a[0]==a[3]&&a[0]==1&&a[6]==0){ a[6]=1;flag=1;return flag; }else if(a[0]==a[6]&&a[0]==1&&a[3]==0){ a[3]=1;flag=1;return flag; }else if(a[3]==a[6]&&a[3]==1&&a[0]==0){ a[0]=1;flag=1;return flag; }else if(a[0]==a[4]&&a[0]==1&&a[8]==0){ a[8]=1;flag=1;return flag; }else if(a[0]==a[8]&&a[0]==1&&a[4]==0){ a[4]=1;flag=1;return flag; }else if(a[8]==a[4]&&a[4]==1&&a[0]==0){ a[0]=1;flag=1;return flag; }else if(a[4]==a[1]&&a[4]==1&&a[7]==0){ a[7]=1;flag=1;return flag; }else if(a[1]==a[7]&&a[1]==1&&a[4]==0){ a[4]=1;flag=1;return flag; }else if(a[4]==a[7]&&a[4]==1&&a[1]==0){ a[1]=1;flag=1;return flag; }else if(a[2]==a[5]&&a[2]==1&&a[8]==0){ a[8]=1;flag=1;return flag; }else if(a[8]==a[5]&&a[8]==1&&a[2]==0){ a[2]=1;flag=1;return flag; }else if(a[2]==a[8]&&a[2]==1&&a[5]==0){ a[5]=1;flag=1;return flag; }else if(a[2]==a[4]&&a[2]==1&&a[6]==0){ a[6]=1;flag=1;return flag; }else if(a[2]==a[6]&&a[2]==1&&a[4]==0){ a[4]=1;flag=1;return flag; }else if(a[4]==a[6]&&a[4]==1&&a[2]==0){ a[2]=1;flag=1;return flag; }else if(a[3]==a[4]&&a[3]==1&&a[5]==0){ a[5]=1;flag=1;return flag; }else if(a[4]==a[5]&&a[4]==1&&a[3]==0){ a[3]=1;flag=1;return flag; }else if(a[3]==a[5]&&a[5]==1&&a[4]==0){ a[4]=1;flag=1;return flag; }else if(a[6]==a[7]&&a[6]==1&&a[8]==0){ a[8]=1;flag=1;return flag; }else if(a[7]==a[8]&&a[7]==1&&a[6]==0){ a[6]=1;flag=1;return flag; }else if(a[6]==a[8]&&a[6]==1&&a[7]==0){ a[7]=1;flag=1;return flag; } } return flag; } int main(){ int n; int a[9]; cin>>n; for(int i=0;i<n;i++){ for(int j=0;j<9;j++){ cin>>a[j]; } if(shewin(a)==1)cout<<kong(a)+1<<endl; else if(shewin(a)==0) cout<<0<<endl; else cout<<(-1)*(kong(a)+1)<<endl; } return 0; }
flag=1,Alice赢;flag=0,平局;flag=-1,Bob赢。
差一步就赢的时候,要把这步下了。
在考试的过程中,我发现了一个自己一直没有注意到的错误:if(a[0]==a[1]==2)是不可以的 而a[0]=a[1]=2是可以的 所以必须写成 if(a[0]==a[1] && a[0](或者a[1])==2)