我的作业之旅之程序设计思维CSP-M1(共三道)

题1:咕咕东的奇遇

题干
题干思路
这个题目很明显利用字母的ACSII码来求解,任意两个字母之间不能确定顺时针转和逆时针转哪个用的步数更短,就都求出来,一个是ACSII码相减的绝对值,一个是26-前者,将两者相比较,取小的那个数累加就是结果。
代码

#include<iostream>
#include<string>
#include<string.h>
using namespace std;
int main()
{
	char zi1='a';
	char zi2[10000];
	int ans,an1,an2,cha;
	ans=0;
	int i=0;
	cin>>zi2;
	while(zi2[i])
	{
		cha=zi2[i]-zi1;
		if(cha>=0)
		an1=cha;
		else
		an1=-cha;
		an2=26-an1;
		if(an1<=an2)
		ans=ans+an1;
		else
		ans=ans+an2;
		zi1=zi2[i];
		i++;
	}
	cout<<ans<<endl;
}

题2:咕咕东想吃饭

题干
题意思路
由题意可知,1.两种方案可以买无数次,2.第一天没有前一天的券,3.最后一天不能买券。
那么其实每一天的生煎其实是由两部分组成的,一个是今天买的,一个是前一天剩的,由于一天之内买偶数次买一送一的套餐与两天买相同数量的两个生煎套餐等价,我们可以视作一天内购买买一送一的套餐的次数只有1和0两种情况,这个次数也代表当天给第二天留的生煎数,即(当天生煎数-前一天剩下的生煎数(0/1))%2=当天留给第二天的生煎数。由此我们可知,若当天的生煎数<前一天剩下的生煎数或者最后一天留给第二天的生煎数>0,不符合条件。
代码

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

题3:可怕的宇宙射线

题干
12
思路
这道题用dfs+剪枝优化。
将宇宙看做一个大的坐标系,起点看做坐标原点,8个运动方向即代表着坐标的8种加减方式,每经过一个坐标就标记一下该位置,若该位置没被标记过,就计数增加,当该层遍历到达终点时,更改运动方向和运动步数,进行下一层遍历直到遍历层数到达给定层数。
但是当遍历层数足够多,运动路径足够长时,很有可能同一层的路径会重合,即同一层某个起点的坐标和运动方向都相等,那么他们接下来的运动路径一定相等,若是重复查询,时间复杂度太大,便需要将重复的路径删减掉。
用一个四维数组标记由坐标、方向和层数对应的新的一层起点,当其被标记说明路径重复,就在递归函数里返回。
代码

#include<iostream>
#include<math.h>
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include<cstring>
using namespace std;
int n;//扩展多少次 
int l[40];//每次扩展的长度
int po[330][330];//用来标记每一个坐标
int duan[330][330][8][31];//用来标记端点层数 
//int dx[]={0,1,-1,1,-1,1,-1,0};
//int dy[]={1,1,1,0,0,-1,-1,-1}; 
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1}; 
int kk=0;//初始 
int num=0;
//0->1/2;1->0/3;2->0/4;3->1/5;4->2/6;5->3/7;6->4/7;7->5/6;
/*int direc1(int m)
{
	switch(m){
		case 0:
			return 1;
		case 1:
			return 0;
		case 2:
			return 0;
		case 3:
			return 1;
		case 4:
			return 2;
		case 5:
			return 3;
		case 6:
			return 4;
		case 7:
			return 5;
	}
}
int direc2(int m)
{
	switch(m){
		case 0:
			return 2;
		case 1:
			return 3;
		case 2:
			return 4;
		case 3:
			return 5;
		case 4:
			return 6;
		case 5:
			return 7;
		case 6:
			return 7;
		case 7:
			return 6;
	}
}*/
void chushi() 
{
	for(int i=0;i<330;i++)
	for(int j=0;j<330;j++)
	{
		po[i][j]=-1;
	}
	
}
void find(int x,int y,int s,int i)//给当前起点的坐标和运动方向和循环层数 
{
	//cout<<s<<endl;
	if(i>=n)
	return;
	if(duan[x][y][s][i]) 
	return;
	duan[x][y][s][i]=1;
	int r=l[i];//要走的个数
	int dx1=dx[s];
	int dy1=dy[s];
	for(int j=0;j<r;j++)
	{
		x=x+dx1;
		y=y+dy1;
		if(po[x][y]==-1)
		{
			num++;
		}
		po[x][y]++;
	}
//	duan[x][y]=i;
	int s1=s+1;
	if(s1>7)
	{
		s1=0;
	}
	
	find(x,y,s1,i+1);
	int s2=s-1;
	if(s2<0)
	{
		s2=7;
	}
	find(x,y,s2,i+1);
}
int main()
{
	int x0;
	int y0;//起点坐标 ,该点未占 
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&l[i]);
	}
	chushi();
//	memset(po,-1,90000);
	x0=150;
	y0=150;
	find(x0,y0,kk,0);
	printf("%d\n",num);
}

以上就是我的csp-M1的模拟总结啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值