【Week4】CSP模拟测试题

A题

题意:
一个圆环包含26个英文字母,顺时针从a到z排列,有一个指针指向a,每次可以顺时针或逆时针旋转一格。如a顺时针旋转到z,逆时针旋转到b。现在有一个字符串(长度<=10000),请输出要得到这个字符串最少需要旋转的次数。

**思路:**将指针的位置随着字符串的位置移动,判断指针所指与指针下一个字符之间的距离a,顺时针转动的距离等于26-a,做判断

代码:

#include <cstdio>
#include<iostream>
#include<algorithm> 
#include<string>
 
using namespace std;
 
 
int main() 
{
string s;
cin>>s;
int tot=0;
char now = 'a';
int term = 0;
int term0 = 0;
for(int i=0;i<s.size();i++)
{
if(now == s[i]) continue;
else if(now > s[i])  term = now -s[i];
else if (now < s[i]) term = s[i] - now;
term0 = 26 - term;
if(term >= term0) tot += term0;
else tot += term;
 
now = s[i];
}
cout<<tot;
 
return 0;
}

总结:
之前思路有问题,用双向链表来做的,一开始想的是双向链表指针可以向前向后。后面发现,顺时指针到z就截止所以每次都要重新改变链表头指针的位置,可是反向链表的头指针无法改变,需要进一步的改进了解。

B题

题意:
咕咕东考试周开始了,考试周一共有n天。他不想考试周这么累,于是打算每天都吃顿好的。他决定每天都吃生煎,咕咕东每天需要买ai个生煎。但是生煎店为了刺激消费,只有两种购买方式:①在某一天一次性买两个生煎。②今天买一个生煎,同时为明天买一个生煎,店家会给一个券,第二天用券来拿。没有其余的购买方式,这两种购买方式可以用无数次,但是咕咕东是个节俭的好孩子,他训练结束就走了,不允许训练结束时手里有券。咕咕东非常有钱,你不需要担心咕咕东没钱,但是咕咕东太笨了,他想问你他能否在考试周每天都能恰好买ai个生煎

Input

输入两行,第一行输入一个正整数n(1<=n<=100000),表示考试周的天数。
第二行有n个数,第i个数ai(0<=ai<=10000)表示第i天咕咕东要买的生煎的数量。

Output

如果可以满足咕咕东奇怪的要求,输出"YES",如果不能满足,输出“NO”。(输出不带引号)

题意:
出现NO的情况有两种
(1)今天有卷可以用但是不买生煎直接退出输出NO
(2)最后一天,买完生煎以后还剩一张劵输出NO
开始判断中间的天,到第i天:如果今天有劵可以用,先把劵juan–,ai–.先两个两个的买保证最好不要剩劵,判断(ai % 2 是否等于0)如果不等于0,则juan++,第二天有劵用

代码:

#include <cstdio>
#include<iostream>
#include<algorithm> 
#include<string>
 
using namespace std;
 
 
int main() 
{
int n;
cin>>n;
int juan=0;
for(int i=0;i<n;i++)
{
int ai;
cin>>ai;
if(juan == 1)//如果有券,先把劵用了 
{
if(ai == 0)
{
    cout<<"NO";
    return 0;
    }
    else
    {
            ai--;
            juan--;
}
}
if(ai % 2 == 0)
   continue;
else if(ai % 2 == 1)
   juan++; 
 
}
if( juan == 1)
   cout<<"NO";
else 
   cout<<"YES";
 
return 0;
}

总结:
这道模拟题的场景要比第一题的难,但是可以变为第i天考虑,考虑第i天的情况,然后对特殊情况进行处理。

C题

题意:
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的左右45度方向分裂出两条宇宙射线,同时威力不变。宇宙射线会分裂n次(n<=30),每次分裂后会在分裂方向上前进ai个单位长度(ai<=5)。请输出有多少个位置会被宇宙射线影响到。

思路:这道题要用到剪枝才会降低时间复杂度,用到dfs

代码:

#include <iostream>
#include<queue>
 
using namespace std;
int n;
int s[32];//分裂次数
int road[400][400];//记录是否经过过这个位置
int visit[400][400][32][8];//记录是否分裂过这个方向
int dx[] ={ 1,1,0,-1,-1,-1,0,1};
int dy[] ={0,1,1,1,0,-1,-1,-1};
int tot=0;
 
struct Node
{
int x;//记录位置 
int y;
int sep;//分裂个数
int dire;//分裂方向 
};
 
void dfs(int x,int y,int sep,int dire)
{
//剪枝 
if(sep> n) return;
if(visit[x][y][sep][dire]) return;//经历过此分裂方向
visit[x][y][sep][dire] = 1;
for(int i=0;i<s[sep];i++)
{
x += dx[dire];
y += dy[dire];
if(road[x][y] != 1)
{
road[x][y] = 1;
tot++;
}
 }
 sep++;
 dfs(x,y,sep,((dire+1)%8));
 dfs(x,y,sep,((dire+7)%8)); 
 
 } 
 
 int main()
 {
         cin>>n;
         for(int i=0;i<n;i++)
         {
                 cin>>s[i];
 }
 dfs(200,200,0,0);
 cout<<tot<<endl;
  } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值