CCF-CSP考试历年真题题型分类
当你加上这个时,只要你不输入 ^Z(ctrl+z) , 条件为真,就会一直循环下去,只有你输入 ^Z,条件为假,终止循环。
BC100 直角三角形图案
#include
using namespace std;
int main()
{
int n = 0;
while (cin>>n)//大家在分组输入时直接用起来呀!
{
for (int i = 0; i < n; i++)
{
for (int a = 0; a <= i; a++)
printf("* ");
printf("\n");
}
}
return 0;
}
AcWing 3777. 砖块
题目大意:求翻转相邻的两个砖块能否是所有颜色都相同!!
思路:递推!强调递推只是一种思路,没有模板!!!
砖块翻转2次以上都是重复的,因此只需要判断它翻转1次还是0次!!问题就简化成为判断此时的砖块需不需要翻转!!
我们假设所有砖块最后都能翻转成B,从1—n-1,进行比较判断第i个颜色是否与B相同,不同则翻转i与i+1个,依次判断完全后会发现1–n-1都翻转成为了B,此时第n个无法翻转,只需判断第n个颜色即可!
同理,假设最后都能翻转成W,如果两种假设都不能实现,则样例无法满足!!!
#include
using namespace std;
int n;
void update(char &c)//翻转第i个字符
{
if(c=='W') c='B';
else c='W';
}
bool check(string s,char c)
{
vector<int> v;//存储是---第i次操作
for(int i=0;i<n-1;i++)//存储在[0,n-1]----翻转[0,n-2]
{
if(s[i]!=c)//如果不是想要的字符----就翻转
{
update(s[i]);
update(s[i+1]);
v.push_back(i);//记录下翻转了第[i,i+1]个砖块
}
}
if(s[n-1]!=s[0]) return false;//---翻转过程结束后,若最后一个字符与其他字符不一致
cout<<v.size()<<endl;//翻转操作的次数
for(auto x:v) cout<<x+1<<" ";//+1的原因---下标的原因
if(v.size()) cout<<endl;//若是---没有翻转过---则比翻转过少一个换行
return true;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
string s;
cin>>s;
if(!check(s,'W')&&!check(s,'B'))//这段代码&&前面不满足后面就不再执行,因此方便了代码书写!
cout<<-1<<endl;
}
return 0;
}
AcWing 1208. 翻硬币
如果通过每次翻转两枚相邻硬币,能从状态一变为状态二,则两个状态之间必定有偶数个不同状态的硬币。
模拟法:
从最左侧开始遍历,如果该位置硬币状态与目标不同,就翻动该位置和该位置后面的两枚硬币。
因为题目说了有解,所以遍历到倒数第二枚的时候,所有硬币状态就与目标相同了。
这个方法也有点贪心的思路,每次追求当前位置状态与目标状态一致。我还是喜欢称它为模拟法。
#include
using namespace std;
string st,ed;
int ans;
void update(char &c)//翻转第i个字符
{
if(c=='o') c='*';
else c='o';
}
int solve()
{
for(int i=0;i<st.size()-1;i++)//遍历[0,n-1]的字符
{
if(st[i]!=ed[i])
{
update(ed[i]);//同时翻转[i,i+1]两枚硬币
update(ed[i+1]);
ans++;//返回的答案
}
}
return ans;
}
int main()
{
cin>>st;
cin>>ed;
cout<<solve()<<endl;
return 0;
}
AcWing 1211. 蚂蚁感冒
AcWing 1211. 蚂蚁感冒—讲解
#include
using namespace std;
const int N=50+10;
int a[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int l=0;//感冒蚂蚁的右边---向左走
int r=0;//感冒蚂蚁的左边---向右走
for(int i=1;i<n;i++)
{
if(abs(a[0])<abs(a[i]) && a[i]<0)
l++;
if(abs(a[0])>abs(a[i]) && a[i]>0)
r++;
}
if(a[0]>0)//当感冒蚂蚁---向右走
{
if(l!=0)
cout<<l+r+1<<endl;
else //特殊情况
cout<<1<<endl;
}
else//当感冒蚂蚁---向左走
{
if(r!=0)
cout<<l+r+1<<endl;
else //特殊情况
cout<<1<<endl;
}
return 0;
}
AcWing 3433. 吃糖果
#include
using namespace std;
const int N = 22;
int dp[N];
int main()
{
int n;
cin >> n;
dp[0]=dp[1]=1;
for(int i=2;i<=n;i++)
dp[i]=dp[i-1]+dp[i-2];
cout<<dp[n]<<endl;
return 0;
}
AcWing 821. 跳台阶
#include
using namespace std;
const int N = 22;
int dp[N];
int main()
{
int n;
cin >> n;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++)
dp[i]=dp[i-1]+dp[i-2];
cout<<dp[n]<<endl;
return 0;
}
#include
using namespace std;
const int N=110;
int rely[N];//记录i的依赖----i依赖于rely[i]
int t[N];//每个科目的训练需要时间
int early[N];
int late[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>rely[i];//存储i的依赖是rely[i]
for(int i=1;i<=m;i++)
cin>>t[i];
//正向计算---最早开始时间
for(int i=1;i<=m;i++)
{
if(!rely[i])//如果不依赖别的科目=1
early[i]=1;
else //如果依赖别的科目=别的科目最早开始时间+别的科目的训练时间
early[i]=early[rely[i]]+t[rely[i]];
cout<<early[i]<<" ";
}
cout<<endl;
//计算最晚开始时间---倒着计算
bool success=true;//标记---每一个最晚时间是否合法
for(int i=m;i>=1;i--)
{
late[i]=n-t[i]+1;//i不被后面的科目所依赖时
for(int j=i;j<=m;j++)//找到后面的j---在依赖i
{
if(rely[j]==i)//i被后面的i所依赖---可能有多个依赖于i的
late[i]=min(late[i],late[j]-t[i]);//最晚时间要尽可能的早些
}
if(late[i]<1)//最晚时间不合法时
success=false;
}
if(success)//当每一个科目都满足要求时
{
for(int i=1;i<=m;i++)
cout<<late[i]<<" ";
}
return 0;
}
AcWing 4510. 寻宝!大冒险!
对应+匹配+不越界
用pair存储绿化图中非零坐标,二维数组存储藏宝图坐标
遍历pair,分别以pair中的点作为藏宝图左下角的点
边缘判断:
绿化图和藏宝图上1的数量必须对应,当两者个数相等时进行判断
对应+匹配+不越界
题目超时的原因在于存储大地图的稀疏矩阵太大,遍历比较耗时长。
本解法利用局部地图减少了遍历的范围。
#include
using namespace std;
const int N= 1e3+10,M=55;
typedef pair<int,int> PII;
#define x first
#define y second
int b[M][M];
PII tree[N];
int main()
{
int n,L,S;//树的棵数、绿化图和藏宝图的大小
cin>>n>>L>>S;
for(int i=0;i<n;i++) cin>>tree[i].x>>tree[i].y;
int tc=0;//记录藏宝图上树的个数
for(int i=S;i>=0;i--)//---注意坐标系的读入
for(int j=0;j<=S;j++)
{
cin>>b[i][j];
tc+=b[i][j];
}
int ans=0;//统计答案的个数
for(int i=0;i<n;i++)
{
int sx=tree[i].x;
int sy=tree[i].y;
if(sx+S>L||sy+S>L)//如果地图上越界 ---经典的错误,标准的零分
continue;
int cnt=0;//记录地图相应区域上---树的个数
bool flag=true;//是否相匹配
for(int j=0;j<n;j++)
{
int x=tree[j].x;
int y=tree[j].y;
if(x>=sx && x<=sx+S && y>=sy && y<=sy+S)//在区域内
if(!b[0+x-sx][0+y-sy])//地图上是树的位置---藏宝图上不是树时
{
flag=false;//直接不匹配---返回
break;//不需要再判断下去了
}
else
cnt++;
}
if(cnt==tc && flag)//个数相同---并且---匹配成功
ans++;
}
cout<<ans<<endl;
return 0;
}
AcWing 4281. 序列查询新解
#include
using namespace std;
const int N=1e5+10;
typedef long long LL;
int n,m;
int a[N];
LL R;
LL get(int l,int r) // 求g[l] + g[l + 1] + ... + g[r]
{
if (l/R==r/R)//如果仅有一小段时
return (LL)(r-l+1)*(l/R);
//g(x)有多段时
int a=l/R+1,b=r/R-1;
LL res=(a+b)*(LL)(b-a+1)/2*R; // 中间部分
res+=(a-1)*(LL)(a*R-l); // 左边界
res+=(b+1)*(LL)(r-(b*R+R)+1); // 右边界
return res;
}
int main()
{
cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i];
a[n+1]=m;
R=m/(n+1);
LL res=0;
for (int i=0;i<=n;i++)
{
int l=a[i];//[l,r]在该区间上a[i]的取值相同
int r=a[i+1]-1;
int x=l/R;//[l,r]区间对应的g(x)的取值
int y=r/R;
if (y<=i || x>=i)//若 g(x)每一小段都在a[i]--[l,r]区间的下方---或上方
{
res+=abs((LL)i*(r-l+1)-get(l,r));//|f(x)-g(x)|
}
else//有交集时
{
int mid=i*R;//交点的最左边 ---i=mid/R
res+=abs((LL)i*(mid-l+1)-get(l,mid)); // 左半边 |f(x)-g(x)|
res+=abs((LL)i*(r-mid)-get(mid+1,r)); // 右半边 |f(x)-g(x)|
}
}
cout<<res<<endl;//输出误差
return 0;
}
AcWing 3293. 风险人群筛查
阅读理解:“连续 k 个或更多坐标均位于矩形内(含边界)”是说明last>=k,并不是有>k个不同点位于高危区域内
#include
using namespace std;
const int N=1e3+10;
int n;//居民数
int k;//连续k个坐标
int t;//每个居民共t个坐标
int res;//经过人数
int ans;//逗留人数
int main()
{
int x1,y1,x2,y2;//矩形框的坐标
cin>>n>>k>>t>>x1>>y1>>x2>>y2;
while(n--)
{
bool pass=false;
bool wait=false;
int s=0;//记录连续停留时间
for(int i=0;i<t;i++)
{
int x,y;
cin>>x>>y;
if(x>=x1 && x<=x2 && y>=y1 && y<=y2)//处在高危地区
{
s++;
pass=true;
if(s>=k)
wait=true;
}
else
s=0;
}
if(pass)
res++;
if(wait)
ans++;
}
cout<<res<<endl<<ans<<endl;
return 0;
}
AcWing 3283. 回收站选址
#include
using namespace std;
const int N =1E3+10;
typedef pair<int,int> PII;
#define x first
#define y second
PII q[N];
int n;
//左上-上-右上-右-右下-下-左下-左
int dx[8]={
-1,-1,-1,0,1,1, 1, 0};
int dy[8]={
-1, 0, 1,1,1,0,-1,-1};
int ans[5];//返回答案
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>q[i].x>>q[i].y;
for(int i=0;i<n;i++)
{
int s[8]={
0};//存储第i个点的八个方向上---点的信息
for(int j=0;j<n;j++)
{
for(int k=0;k<8;k++)
{
int a=q[i].x+dx[k];
int b=q[i].y+dy[k];
if(a==q[j].x && b==q[j].y)//如果某方向上有垃圾
s[k]++;
}
}
if(s[1] && s[3] && s[5] && s[7])//满足--上下左右都有垃圾
ans[s[0]+s[2]+s[4]+s[6]]++;
}
for(int i=0;i<5;i++)
cout<<ans[i]<<endl;
return 0;
}
AcWing 3278. 小明种苹果