第四周CSP模拟

第四周CSP模拟

A - 咕咕东的奇遇

  • 题意
    有一个子母钟,从A到Z首尾相接,起点为A。输入一个字符串,输出子母钟要得到该字符串要走的最小步数。

  • 输入输出
    Input
    hzet
    Output
    31
    在这里插入图片描述

  • 解题思路:
    简单的贪心算法,输入数据为string类型,按照字符依次读取,每次求出子母钟从当前位置到下一个位置的最短距离,即比较顺时针和逆时针转哪个步数更少,更新指针位置。

  • 代码实现

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm> 
using namespace std;

int main()
{
	string a;
	cin>>a;
	int i=0,j=0,p=0;
	int length=a.length(); //字符串长度
	for(int k=0;k<length;k++)
	{
		p=a[k]-'a';
		j=j+min(abs(p-i),26-abs(p-i));//求出较小的步数
		i=p; 
	} 
	
	cout<<j<<endl;
	
	return 0;
 } 

B - 咕咕东想吃饭

  • 题意:考试周有n天,咕咕东在每天希望买a1,a2,a3…an个生煎。有两种购买方式,第一种是一次性买两个,第二种是只拿一个生煎并领一张券第二天来领另一个生煎。问能否在n天理每天买到a[i]个生煎。

  • 输入输出
    第一行输入n天,第二行输入每天需要买的生煎a1到an。能买到输出YES,不能输出NO。
    Input
    4
    1 2 1 2
    Output
    YES
    在这里插入图片描述

  • 解题思路
    本题也较为简单,有两种购买方式,如果是偶数则可以视为第一种,奇数可以视为第二种。偶数个则在当天就可以消费掉,而奇数个需要后面再购买一次奇数个才可以抵消。如:2,4可以用第一种购买方法,而1,2,1则是第一天买一个领一张券,第二天领取前一天的并再买一个领一张券,第三天再领取前一天的,观察得只需要有两天购买奇数个就可以抵消掉
    定义count为计数器,每次遇到购买数为奇数的计数器加一,保证在遇到购买数为0的天数之前和在结束之前count为偶数,该购买方案就可以成立。

  • 代码实现:

#include<iostream>
using namespace std;
 
int main()
{
    int n;
    cin>>n;
    int a[200000];
    for(int i=0;i<n;i++)
    	cin>>a[i];
    int count=0;
    for(int j=0;j<n;j++)
    {
    	if(a[j]==0)
    	{
    		if(count%2==1)
    		{
    			cout<<"NO"<<endl;
				return 0;	
			}
			else
				count=0;
		}
    	if(a[j]%2==1)
    		count=count+1;
	}
	if(count%2==0)
		cout<<"YES"<<endl;	
	else
		cout<<"NO"<<endl;
	return 0;
}

C - 可怕的宇宙射线

  • 题意:神奇的宇宙射线,每走一段就会分裂到两个方向,分裂的方向分别为原方向向左和向右偏45度。该宇宙射线最多分裂三十次,每次分裂后走的距离不大于5,需要计算该射线最后覆盖的格子数。宇宙射线分裂规律如下图:
    在这里插入图片描述

  • 输入输出
    第一行输入分裂次数,第二行输入每次分裂走的距离。
    Input
    4
    4 2 2 3
    Output
    39
    在这里插入图片描述

  • 解题思路:
    刚开始看到这道题会有点懵逼,因为神奇的宇宙射线分裂的实在是太放肆了。不过仔细思考发现并不是没有规律可循,因为它分裂的规律是一定的,知道了它分裂的方向和要走的长度即可以推出它走过的格子数。同时射线每次分裂成两条,可以发现它的分裂数量按照层数指数增加,故可以想到bfs的方法。

    单纯的bfs不进行剪枝数据量指数增长复杂度过大,会直接爆栈。故想到进行剪枝,在分裂到一定的量之后会有很多方向重复,而同一层的前进步数又相同,故计算一次即可。考虑将原来的二维标记数组改为四维数组,分别记录分裂点的方向、层数以及横纵坐标,重复的点不再入队,如此一来时间复杂度会大大降低。

    结构体node成员为横纵坐标、方向和层数,进行初始化,结构体transfer记录方向更加方便。从起始点开始记录坐标、方向和层数,入队,开始bfs。每次到达一个新的分裂点先判断该点是否已经被标记,若标记过则不再入队,变量ans记录到达方格数,若未标记ans加上相应的步数。最后输出ans即为到达的方格数。

  • 代码实现:

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
int n;
int a[40];
struct node
{
	int x;
	int y;
	int dir;
	int level;
	node(){}
	node(int xx,int yy,int tt,int ll)
	{
		x=xx;
		y=yy;
		dir=tt;
		level=ll;
	}
};

struct transfer
{
	int x1;
	int y1;
	int x2;
	int y2;
	transfer(){}
	transfer(int aa,int bb,int cc,int dd)
	{
		x1=aa;y1=bb;x2=cc;y2=dd;
	}
};

transfer op[10];
bool viss[510][510];
bool vis[35][510][510][8];
queue<node> q;
int ans=0;

void bfs()
{
	int sx,sy;
	sx=250;
	sy=250;
	int num=a[0];
	while(num--)
	{
		sx+=0;
		sy+=1;
		viss[sx][sy]=1;
		ans++;
	}
	q.push(node(sx,sy,0,1));
	vis[1][sx][sy][0]=1;
	while(!q.empty())
	{
		node before=q.front();
		q.pop();
		if(before.level>=n)
			break;
		int steps=a[before.level];
		int dx1,dy1,dx2,dy2;
		dx1=before.x;dy1=before.y;dx2=before.x;dy2=before.y;
		while(steps--)
		{
			dx1+=op[before.dir].x1;
			dy1+=op[before.dir].y1;
			dx2+=op[before.dir].x2;
			dy2+=op[before.dir].y2;
			if(!viss[dx1][dy1])
			{
				viss[dx1][dy1]=1;
				ans++;
			}
			if(!viss[dx2][dy2])
			{
				viss[dx2][dy2]=1;
				ans++;
			}
		}
		int op1=(before.dir+7)%8;
		int op2=(before.dir+1)%8;
		if(!vis[before.level+1][dx1][dy1][op1])
		{
			vis[before.level+1][dx1][dy1][op1]=1;
			q.push(node(dx1,dy1,op1,before.level+1));
		} 
		if(!vis[before.level+1][dx2][dy2][op2])
		{
			vis[before.level+1][dx2][dy2][op2]=1;
			q.push(node(dx2,dy2,op2,before.level+1));
		} 
	}
	cout<<ans<<endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	memset(vis,0,sizeof(vis));
	memset(viss,0,sizeof(viss));
	op[0]=transfer(-1,1,1,1);
	op[1]=transfer(0,1,1,0);
	op[2]=transfer(1,1,1,-1);
	op[3]=transfer(1,0,0,-1);
	op[4]=transfer(1,-1,-1,-1);
	op[5]=transfer(0,-1,-1,0);
	op[6]=transfer(-1,-1,-1,1);
	op[7]=transfer(-1,0,0,1);
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	bfs();	
	return 0;
}
发布了19 篇原创文章 · 获赞 0 · 访问量 650

猜你喜欢

转载自blog.csdn.net/Hdjjdsbjj/article/details/104982093
今日推荐