洛谷训练(4)P1022 计算器的改良、P1003铺地毯、P1464 Function

P1022 计算器的改良

点击查看题目描述

主要思路
  • 首先明确:所有的一元一次方程都可化为kx+b=0的形式,即可得到x=-b/k
  • 采用string存储输入的方程
  • 要注意多位整数的处理
  • 一旦遇到符号,前面的整数就累加进b
  • 遇到字母,整数累加进k,此处要注意字母系数为1省略不写的情况
  • 特别注意最后一位整数要单独处理
#include<bits/stdc++.h>
using namespace std;
//最终化成kx+b=0;
int main()
{	
	string c;
	cin>>c;//存输入的方程 
	char x;	 //存未知数 
	float fh=1;//存符号
	float flag=1;//等号右边则为-1 
	float n=0,num=0;//n当前单个数字,num最终数例如读取两位数num=num*10+n
	float k=0,b=0;//k是未知数的最终系数,b是其余常数和  
	int len=c.length();
	//单独判断第一个字符 
	if(c[0]=='-')fh=-1;
	else if(c[0]>='a'&&c[0]<='z')
	{
		x=c[0];
		k++;
	}
	else if(c[0]>='0'&&c[0]<='9')
	{
		n=c[0]-'0';
		num=num*10+n;
		fh=1;
	}
	//遍历剩余字符 
	for(int i=1;i<len;i++)
	{
		if(c[i]>='0'&&c[i]<='9')
		{
			n=c[i]-'0';
			num=num*10+n;
		}
		else if(c[i]>='a'&&c[i]<='z')
		{
			x=c[i];
			k+=fh*flag*num;	//遇到字母就累加系数 
			num=0;
			if(c[i-1]=='='||c[i-1]=='-'||c[i-1]=='+')k+=flag*fh;		 
		}		
		else //一旦监测到其余符号,则 b马上累加 ,所以最后一个数字没办法累加,要在外面处理 
		{
			b+=num*flag*fh;
			num=0;
			fh=1;			 
			if(c[i]=='=')flag=-1;	
			else if(c[i]=='-')fh=-1;
			else if(c[i]=='+')fh=1;
		}
	} 
	if(c[len-1]>='0'&&c[len-1]<='9')//单独判断最后一个是数字时,由于后面没有符号了所以强制累加
	{
		b+=num*flag*fh;	
	} 	
	double re=b/k;
	if(b==0)printf("%c=0.000\n",x);
	else printf("%c=%.3lf\n",x,-1*re);
	return 0;
} 

P1003铺地毯

点击查看题目描述

主要思路
  • 刚开始真的不能再真的来个“全真模拟”——结果数组爆了

    傻逼代码如下:

#include<bits/stdc++.h>
using namespace std;
int flag[200001][200001];
int main()
{	
	int n;
	cin>>n;
	for(int e=1;e<=n;e++)
	{
		int a,b,g,k;
		cin>>a>>b>>g>>k;
		for(int i=a;i<=a+g;i++)
		{
			for(int j=b;j<=b+k;j++)
			{
				flag[i][j]=e; 
			}
		}
	}
	int x,y;
	cin>>x>>y;
	if(flag[x][y]==0)cout<<-1;
	else cout<<flag[x][y];
	return 0;
} 
  • 后来经过大佬的提点,换了一种思路

    只用记录对角的两个顶点坐标不就好了吗!!!

    然后逆序搜索比较

#include<bits/stdc++.h>
using namespace std;
int flag[100001][5];
int main()
{	
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int a,b,g,k;
		cin>>a>>b>>g>>k;
		flag[i][1]=a;
		flag[i][2]=b;
		flag[i][3]=a+g;
		flag[i][4]=b+k;
	}
	//逆序搜索 
	int x,y;
	cin>>x>>y;
	for(int i=n;i>=1;i--)
	{		
		if(x>=flag[i][1]&&x<=flag[i][3]&&y>=flag[i][2]&&y<=flag[i][4])
		{
			cout<<i;
			break;
		}	
	}
	return 0;
} 

P1464 Function

点击查看题目描述

主要思路
  • 输入的数在10^19以内,如果直接递归肯定会超时
  • 开一个三维数组,采用记忆化搜索

记忆化搜索=搜索的形式+动态规划的思想

记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。

#include<bits/stdc++.h>
using namespace std;
long long f[21][21][21];
long long w(long long a,long long b,long long c)
{
	if(a<=0||b<=0||c<=0) return 1;
	if(a>20||b>20||c>20) return w(20,20,20);
	if(a<b&&b<c) 
	{
		if(f[a][b][c]==0)
		{
			f[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
		}
	}
	else 
	{
		if(f[a][b][c]==0)
		{
			f[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
		}
	}
	return f[a][b][c];
}
int main()
{
	memset(f,0,sizeof(f));
	long long a,b,c;
	while(scanf("%lld %lld %lld",&a,&b,&c)&&(a!=-1||b!=-1||c!=-1))
	{
		printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,w(a,b,c));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值