洛谷的题——12月10日^-^

P1002 过河卒

棋盘上 AAA 点有一个过河卒,需要走到目标 BBB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CCC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,AAA 点 (0,0)(0, 0)(0,0)、BBB 点 (n,m)(n, m)(n,m),同样马的位置坐标是需要给出的。

在这里插入图片描述
题目链接:https://www.luogu.com.cn/problem/P1002

我的思路:一开始我以为这是一道宽度优先搜索,但是后来觉得宽度优先搜索应该是搜索最短路径长度,然后想是不是深度优先搜索,深度优先搜索应该是用于是否能够到达终点的
后来看了解析才知道是动态规划。动态规划就是一个填表的操作,这次要填的二维表格的大小和棋盘一样大,每个格子里的内容是到达该点有多少种方法。
由此可以得到状态转移方程是:
S[2][2] = 0 {\text{S[2][2] = 0}} S[2][2] = 0

S [ i ] [ j ] = max ⁡ ( S [ i ] [ j ] , S [ i − 1 ] [ j ] + S [ i ] [ j − 1 ] ) S[i][j] = \max (S[i][j],S[i - 1][j] + S[i][j - 1]) S[i][j]=max(S[i][j],S[i1][j]+S[i][j1])

为什么去第一个是S[2][2]是因为马走日,避免超出数组的界限

需要注意的地方:
这个S数组中的值可能很大,因此需要用unsigned long long来表示。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m;
int x,y;
unsigned long long s[30][30];
bool d[30][30];
const int fx[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
const int fy[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
int main()
{
	scanf("%d%d%d%d",&n,&m,&x,&y);
	n+=2;m+=2;
	x+=2;y+=2;
	d[x][y]=1;
	//标记马的控制范围 
	for(int i=1;i<=8;i++)
	{
		d[x+fx[i]][y+fy[i]]=1;
	}
	s[2][2]=1;
	//动态规划填表 
	for(int i=2;i<=n;i++)
	{
		for(int j=2;j<=m;j++)
		{
			if(d[i][j])
			{
				continue;
			}
			s[i][j]=max(s[i][j],s[i-1][j]+s[i][j-1]);
		}
	}
	cout<<s[n][m]<<endl;
	//printf("%llu\n",s[n][m]);
	return 0;
 } 

P1015 回文数

题目描述

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。

例如:给定一个十进制数 565656,将 565656 加 656565(即把 565656 从右向左读),得到 121121121 是一个回文数。

又如:对于十进制数 878787:

STEP1:87+78=16587+78=16587+78=165
STEP2:165+561=726165+561=726165+561=726
STEP3:726+627=1353726+627=1353726+627=1353
STEP4:1353+3531=48841353+3531=48841353+3531=4884

在这里的一步是指进行了一次 N 进制的加法,上例最少用了 4 步得到回文数 4884。

写一个程序,给定一个 N(2≤N≤10 或 N=16)进制数 M(100 位之内),求最少经过几步可以得到回文数。如果在 30步以内(包含 30 步)不可能得到回文数,则输出 Impossible!。
输入格式

两行,分别是 N,M。
输出格式

如果能在 30步以内得到回文数,输出格式形如 STEP=ans,其中 ans 为最少得到回文数的步数。

否则输出 Impossible!。

我的思路:
这个是一个高精度的题目,无法使用int一类的数字来表示,因此需要使用char数组来表示很大的数。
输入部分:将需要计算的m输入为一个char数组,其中m[0]对应的就是数字的最低位,很神奇吧,明明数字的最低位是最后一个输入的,但是却存在了char数组的第0位,但是这样也为后面的计算带来了方便,数字就是向高位递增的啦,很神奇吧!还有就是需要处理输入的数据,因为输入的是字符,但是我们需要计算的是数字,所以对应了-‘0’和-‘A’+10的操作。
首先需要自己定义加法操作,由于加法操作最多进一位,所以当计算到最高位的时候需要判断是否进位,如果进位,那么char数组的长度就要加一。

然后就是直接30次模拟了
代码

#include<iostream>
#include<cstring>
using namespace std;
int n;
char m[500];
char m_reverse[500];
int len;
bool ishui(char number[500])
{
	//int len=strlen(number);
	for(int i=0;i<len;i++)
	{
		if(number[i]!=number[len-i-1])
		{
			return false;
		}
	}
	return true;
}
void add()
{
	//int len = strlen(m);
	//求的 
	for(int i=0;i<len;i++)
	{
		m_reverse[i]=m[len-i-1];
	}
	//len+=2;
	for(int i=0;i<len;i++)
	{
		m[i]=m[i]+m_reverse[i];
		if(m[i]>=n)
		{
			m[i+1]++;
			m[i]=m[i]-n;
			if(i==len-1)
			{
				len++;
			}
		}
	}
	//while(!m[len-1]) len--;
}
int main()
{
	cin>>n>>m;
	len=strlen(m);
	//cout<<m<<endl;
	int ans=0;
	bool isok=false;
	for(int i=0;i<len;i++)
	{
		if(m[i]>='0'&&m[i]<='9')
			m[i]-='0';
		else
		{
			m[i]=m[i]-'A'+10;
		}
	 } 
	for(int i=0;i<30;i++)
	{
		bool flag = ishui(m);
		//cout<<flag<<endl;
		if(flag)
		{
			cout<<"STEP="<<ans<<endl;
			isok=true;
			break;
			
		}
		add();
		
		ans++;
	}
	if(!isok)
	{
		cout<<"Impossible!"<<endl;
	}
	return 0;
}

P1003 铺地毯

题目地址:https://www.luogu.com.cn/problem/P1003

这一题思路很奇葩,直接从最后一张地毯开始看是否包含(x,y)这个点就好啦!
代码

#include<iostream>
using namespace std;
typedef unsigned long long ull;
ull n;
ull a[10005];
ull b[10005];
ull g[10005];
ull k[10005];
ull x,y;
int main()
{
	
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i]>>b[i]>>g[i]>>k[i];
	}
	cin>>x>>y;
	bool isok=false;
	for(int i=n-1;i>=0;i--)
	{
		if(x>=a[i]&&x<=a[i]+g[i]&&y>=b[i]&&y<=b[i]+k[i])
		{
			cout<<i+1;
			isok = true;
			break;
		}
	 } 
	 if(!isok)
	 {
	 	cout<<-1;
	 }
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值