P1464 Function题解
  • 板块P1464 Function
  • 楼主Gwiazda
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/8/27 08:57
  • 上次更新2024/8/27 09:08:36
查看原帖
P1464 Function题解
1267180
Gwiazda楼主2024/8/27 08:57

初见这就是个水的递归,先考虑暴力

主函数

1.声明a,b,c;

2.循环输入a,b,c,如果均为-1则跳循环;

3.对于每一组输入,输出对应的w(a,b,c)。

w(a,b,c)

1.定义函数参数一条龙服务;

2.分情况写if语句模拟,返回对应的值(抄题干即可)。

暴力代码如下

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL w(LL a,LL b,LL c){
	if(a<=0||b<=0||c<=0) return 1;
	else if(a>20||b>20||c>20) return w(20,20,20);
	else if(a<b&&b<c) return w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
	else return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main(){
	LL a,b,c;
	while(scanf("%lld%lld%lld",&a,&b,&c)){
		if(a==-1&&b==-1&&c==-1) break;
		printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,w(a,b,c));
	}
	return 0;
}

至此,一锤定音。

尘埃,已然落地......个鬼嘞!全超时。

题干告诉我们,a=b=c=15时会出问题,所以我们尝试输入。

然后就发现卡住了,动都不动。

我们转念一想,想到了尝试小一点的三个相同数字,发现

  • 1,1,1,答案是2;
  • 2,2,2,答案是4;
  • 3,3,3,答案是8;
  • 4,4,4,答案是16;

不难发现,n,n,n的答案恰好是2的n次方!

于是我们在w()里写一句特判:

if(a==b&&b==c) return pow(2,n);

现在我们能拿到20pts了,可喜可贺

为了避免函数重复处理大量相同的子问题,我们不妨声明一个三维数组记录每组a,b,c的结果。

也就是记忆化搜索。

详细内容我放在代码注释里,以下是完整AC代码。

#include<bits/stdc++.h>//万能头文件 
using namespace std;
typedef long long LL;//可以用LL代替long long 
LL rem[21][21][21];//函数内只处理1-20 
LL w(LL,LL,LL); 
int main(){
	LL a,b,c;
	memset(rem,-1,sizeof(rem));//初始化数组,赋值-1 
	while(scanf("%lld%lld%lld",&a,&b,&c)){
		if(a==-1&&b==-1&&c==-1) break;//跳出循环 
		printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,w(a,b,c));
	}
	return 0;
}
LL w(LL a,LL b,LL c){
	if(a<=0||b<=0||c<=0) return 1;
	else if(a>20||b>20||c>20) return w(20,20,20);
	else if(rem[a][b][c]!=-1) return rem[a][b][c];//如果已经存过数据,直接返回 
	else if(a==b&&b==c) return rem[a][b][c]=1<<a;//特判,1>>a相当于pow(2,a)
	else if(a<b&&b<c) return rem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
	return rem[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);
}
2024/8/27 08:57
加载中...