【做题笔记】洛谷P1464 Function
我先谔谔一波 /kk 我谔谔
看题第一眼:欸这不就是按题意递归嘛,,直接搞不就好了
3 min 后,重新看题
然后自己手玩了几个样例,噢,递归太多了,铁定会 T 啊......
然后,作为一个从没写过记忆化搜索的蒟蒻,苦苦思索了十几分钟。。。。。。
然后忽然想到可以用一个数组记录每一次的状态,然后如果递归到重复的数字直接返回记录的值,这就叫记忆化搜索!
我竟然就这样把记忆化搜索给 yy 出来了......
然后就是无尽的采坑。。。
首先,就是开了一个叫 \(\mathtt{mem}\) 的三维数组,然后每次递归就查询对应的位置,如果有值就返回,否则再按题目的意思一个一个去把 \(\mathtt{mem}\) 数组赋值。写出来大概就是这个样子:
long long w(long long a,long long b,long long c)
{
if(mem[a][b][c]!=0) return mem[a][b][c];
if(a<=0||b<=0||c<=0) return 1;
else if(a>20||b>20||c>20) mem[a][b][c]=w(20,20,20);
else if(a<b&&b<c) mem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else mem[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);
}
然而又 WA 又 T 的,心酸。。。
然后突然发现数据范围: \([−9223372036854775808,9223372036854775807]\)
那递归开头就去判断如果下标是一个很大的负数咋办???岂不是会出现奇奇怪怪的错误???
所以,可以将函数里的第一行和第二行调换一下,这样就先去判断是否是负数了
long long w(long long a,long long b,long long c)
{
if(a<=0||b<=0||c<=0) return 1;
if(mem[a][b][c]!=0) return mem[a][b][c];
else if(a>20||b>20||c>20) mem[a][b][c]=w(20,20,20);
else if(a<b&&b<c) mem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else mem[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);
}
然而又 WA 了!!!咋回事啊???
于是经过长达十几分钟的手玩数据,发现最后不会返回答案!!!所以在函数最后返回这个值就好了......
long long w(long long a,long long b,long long c)
{
if(a<=0||b<=0||c<=0) return 1;
else if(mem[a][b][c]!=0) return mem[a][b][c];
else if(a>20||b>20||c>20) mem[a][b][c]=w(20,20,20);
else if(a<b&&b<c) mem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else mem[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 mem[a][b][c];
}
这下呢???20分!!!
然后又是十几分钟的手玩数据,突然发现 \(\mathtt{mem}\) 数组的值每次不会被清空。换而言之,在以后我们每次都在使用上次记忆的值。
既然如此,每次把 \(\mathtt{mem}\) 数组清零不久好了???
这个时候主函数就被改成了这样
int main()
{
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c)&&(a!=-1)&&(b!=-1)&&(c!=-1))
printf("w(%d, %d, %d) = %d\n",a,b,c,w(a,b,c));
return 0;
}
还是不行!!!为啥???不难发现,若 \(a,b,c\) 的值过大,记忆数组存不下!!!
如何解决呢?考虑当 \(>20\) 时,并不会对 \(a,b,c\) 本身进行操作,换而言之,\(a=114514\) 和 \(a=21\) 本质是一样的!!!
int main()
{
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c)&&(a!=-1)&&(b!=-1)&&(c!=-1))
{
memset(mem,0,sizeof(0));
printf("w(%d, %d, %d) = ",a,b,c);
//注意,下面的 a,b,c 要被修改,所以得先行输出
if(a>20) a=21;
if(b>20) b=21;
if(c>20) c=21;
printf("%d\n",w(a,b,c));
}
return 0;
}
还是过不了!!!我要被搞疯了
最后还是把错误 yy 了出来, while 里的判断条件会使得如果 \(a,b,c\) 有一个是负数(不是 \(-1\) )就会结束......
最终 \(\mathtt{AC}\) 代码......
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
long long mem[101][101][101]={};
long long w(long long a,long long b,long long c)
{
if(a<=0||b<=0||c<=0) return 1;
else if(mem[a][b][c]!=0) return mem[a][b][c];
else if(a>20||b>20||c>20) mem[a][b][c]=w(20,20,20);
else if(a<b&&b<c) mem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else mem[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 mem[a][b][c];
}
int main()
{
long long a,b,c;
while(scanf("%lld%lld%lld",&a,&b,&c)==3)
{
if((a==-1)&&(b==-1)&&(c==-1)) break;
memset(mem,0,sizeof(0));
printf("w(%lld, %lld, %lld) = ",a,b,c);
if(a>20) a=21;
if(b>20) b=21;
if(c>20) c=21;
printf("%lld\n",w(a,b,c));
}
return 0;
}
所以说我仍然谔谔
【做题笔记】洛谷P1464 Function的更多相关文章
- (水题)洛谷 - P1464 - Function
https://www.luogu.org/problemnew/show/P1464 #include<bits/stdc++.h> using namespace std; #defi ...
- 洛谷P1464 Function HDU P1579 Function Run Fun
洛谷P1464 Function HDU P1579 Function Run Fun 题目描述 对于一个递归函数w(a,b,c) 如果a≤0 or b≤0 or c≤0就返回值11. 如果a> ...
- 洛谷 P1464 Function【记忆化搜索】
题目链接 题目描述 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回值1. 如果a>20 or b>20 or c>20就返回w ...
- 洛谷 P1464 Function【动态规划(递推)/记忆化搜索(递归)】
题目描述 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回值1. 如果a>20 or b>20 or c>20就返回w(20,2 ...
- 洛谷 P1464 Function
题目描述 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回值1. 如果a>20 or b>20 or c>20就返回w(20,2 ...
- 洛谷P1464 Function
对于一个递归函数w(a,b,c)w(a,b,c) 如果a \le 0a≤0 or b \le 0b≤0 or c \le 0c≤0就返回值11. 如果a>20a>20 or b>20 ...
- 洛谷 P1464 Function(简单记忆化)
嗯... 让一切从水开始吧... 水过初赛,但愿复赛能够接着水过... 这道题不记忆化会tle,所以用空间换时间,将每次的答案(只有20*20*20个)存下来,如果之前已经求过,就不需要重复求了... ...
- java实现 洛谷 P1464 Function
import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.S ...
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
随机推荐
- Docker 镜像仓库为什么要分库分权限?
先说一个事故案例: 场景:某大型互联网电商公司,使用一个镜像仓库管理所有Docker镜像.开发者打出的镜像上传到唯一的镜像库,测试通过后,运维环境的 Kubernetes 直接从这个库里拉取镜像,所有 ...
- Winform递归绑定树节点
/// <summary> /// 绑定树节点 /// </summary> /// <param name="pid"></param& ...
- openWRT和LuCI
openwrt是一套集成在板子上的系统,通过ip进入到其页面上 Luci是lua和UCI统一配置接口的合体,实现路由的网页配置界面(相当于一个前端框架)
- java面试记录一:跳表、判断二叉树相同、冒泡排序、cookie和session的区别、设计模式(单例、工厂、模板方法、原型、代理、策略)、抽象类与接口的区别
1.什么是跳表? 跳表实际上就是多层链表 跳表可用在让链表的元素查询接近线性时间 代码结构及java实现参考博客园随笔 2.判断两棵二叉树是否相同?(结构相同,内容相同) 思路:(1)先定义树节点Tr ...
- 搜索字母a或A
Amy觉得英语课实在是无聊至极,他不喜欢听老师讲课. 但是闲着也是闲着,不如做点什么吧?于是他开始数英语书里的字母a和A共出现了多少次. 费了九牛二虎之力终于数完了. 作为一名软件工程专业大学生,他觉 ...
- [USACO10MAR] 伟大的奶牛聚集 - 树形dp
每个点有重数,求到所有点距离最小的点 就是魔改的重心了 #include <bits/stdc++.h> using namespace std; #define int long lon ...
- MapReduce第一个项目 WordCount
参考自林子雨大数据教学: http://dblab.xmu.edu.cn/blog/hadoop-build-project-using-eclipse/ 创建一个文件夹:放入一个文本文件:填 ...
- PHP获取小程序码并返回前端显示图片
小程序的二维码分为小程序码和二维码: 生成小程序二维码文档中说后端来生成. 参考 小程序开发文档资料:https://developers.weixin.qq.com/miniprogram/dev/ ...
- Keep、小红书、美图…独角兽App能拿到新一轮救命钱吗?
大多数人热爱手机,不是因为时尚的外观或者结实的零部件,而是因琳琅满目的App赋予其太多的功能.智能手机最先是清理掉人类的零碎时间,现如今又开始肢解我们大块的时间,或者说,智能手机本身就是生活.在如此背 ...
- javaScript入门(函数)
目录 JavaScript函数 函数是什么 函数返回值 return特点: 递归函数 匿名函数(anoymous) 自执行函数(通过匿名函数实现) 回调函数 闭包函数 构造函数 构造函数两大类 注意事 ...