洛谷 P1464 Function

题目描述

对于一个递归函数w(a,b,c)w(a,b,c)

  • 如果a≤0 or b≤0 or c≤0就返回值11.
  • 如果a>20 or b>20 or c>20就返回w(20,20,20)
  • 如果a<b并且b<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,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)

这是个简单的递归函数,但实现起来可能会有些问题。当a,b,c均为15时,调用的次数将非常的多。你要想个办法才行.

/* absi2011 : 比如 w(30,-1,0)既满足条件1又满足条件2

这种时候我们就按最上面的条件来算

所以答案为1

*/

输入格式

会有若干行。

并以-1,-1,-1−1,−1,−1结束。

保证输入的数在[-9223372036854775808,9223372036854775807]之间,并且是整数。

输出格式

输出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

输入输出样例

输入 #1复制

1 1 1
2 2 2
-1 -1 -1

输出 #1复制

w(1, 1, 1) = 2
w(2, 2, 2) = 4

说明/提示

记忆化搜索

解答:(因为直接用DP+记忆化就好,思路比较简单,直接代码)

/*思路:记忆化*/ 
#include <cstdio>

typedef long long LL;

const int MAX = 21*21*21;		
/*MAX = 20*20*20  error_1:这是我之前的写法,错误点在于,abc <= 20,则应当用21  进制才行*/

int mems[MAX];						//memorys
bool flags[MAX];

int get_index(int a,int b,int c)	//对 a,b,c hash
{	return a*21*21 + b*21 + c;	}

int w(int a,int b,int c){
	//设置出口 
	if(a <= 0||b <= 0||c <= 0)	return 1;
	
	//记忆化
	int index = get_index(a,b,c);
	if(flags[index])	return mems[index]; 
	
	//递归过程 
	if(a < b&&b < c)
		mems[index] = w(a,b,c-1) + w(a,b-1,c-1) - w(a,b-1,c);
	else
		mems[index] = w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
		
	flags[index] = true;
	return mems[index];
}

int main()
{
	LL a,b,c;
	int ans;
	while(scanf("%lld %lld %lld",&a,&b,&c)){
		if(a == -1&&b == -1&&c == -1)	break;
		else if(a <= 0||b <= 0||c <= 0)	ans = 1;
/*error2:我没写这条语句。题目要求同时满足条件1、2时,所以在判断2前要先判断1。因为读入的abc可能是long long型,而真正用到的其实是小于21的数,所以我为了函数传参时可以传int型将判断2的语句提了出来,之后才导致忘了在其之前+判断1的语句。*/
/*error3:此处还发生了一个错误就是,多出了一个判断,而之前我的输出语句是写在else下的,多了这个条件之后,当这条判断成功时不会输出内容了。*/  
		else{
			if(a > 20||b > 20||c > 20)	
				ans = w(20,20,20);
			else
				ans = w(a,b,c);
		}
		printf("w(%lld, %lld, %lld) = %d\n",a,b,c,ans);
/*error4:同error3,自己将输出语句写在了else内(因为当时if中直接break了,所以觉得写在else里没问题),导致多出一个判断的时候存在有的情况没有输出。*/
	} 
	return 0;
}

总结:(针对犯得错误)

总的说来,犯得错误分为两种,一种是读题不清,另一种是代码问题,下面说说解决办法。

读题不清:

首先第一遍读题肯定不可能什么时候都面面俱到,因为还是要以完成功能为前提。但是可以在完成要求的同时针对题目的一个一个要求多考察细节,所以解决办法分两步。

第一步:对于有些难度的题,多用函数将各功能分离,因为题目的要求也是一步步来的,针对每个函数去对应地仔细看题目要求。

第二部:在完成之后,要大致再对应题目看一遍,不能只依赖样例,这样总是会形成以样例为标准而忽略题目要求。

代码问题:

代码问题中又有两个问题,一是自己的代码洁癖,二是对题目要求是否彻底落实。

代码洁癖的问题要引起自己的重视,自己总是为了避免重复代码和为了机器节省空间和操作,总是想把代码写的很简洁,但这样有时会太可以使得自己忽略了本身要实现的功能,所以以后先用自己最有把握实现问题的方式写,当完全通过之后再试着将刚才想改进的地方改进,这样慢慢熟悉了简单的写法之后再在做题中使用。

对题目是否落实的问题其实在解决了代码洁癖的问题和读题不清的问题之后其实就解决了十之八九了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Drdajie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值