【洛谷p1077】摆花
题外废话:
真的超级喜欢这道题
yy一提醒,我发现这道题和【洛谷p2089】 烤鸡有异曲同工之妙(数据更大了更容易TLE呢qwq)
SOLUTION1:(暴搜)
搜索:关于搜索就不用多介绍了吧,这里是用了dfs:dfs函数中有两个变量,rest和i分别表示还需要摆放多少盆花以及现在摆放到第几种花了,因为我们是从0开始枚举,因此如果某种花我们不选择,那就可以看做这种花选择了0盆;
几个返回条件:
1.rest==0时,记录ans++(ans是全局变量)return,不需要满足rest==0&&i=n+1(因为只要rest被枚举完了就可以了,后面的花不摆放就好啦)
2.i==n+1时,return;为什么是i=n+1呢,因为当i=n时,我们并没有枚举第n种花摆放的盆数,如果现在就返回,显然是会对结果造成很大的影响,进而影响整个结果;
3.rest<0时,return;因为此时所有m盆花已经被摆出去了,没有继续搜索的必要,直接return;
核心语句:
其实就一句话:
for(int j=;j<=a[i];j++)
dfs(rest-j,i+);
直接暴力dfs因为实际并没有改变rest和i的值,所以我们连回溯都不需回溯;
以下是完整CODE:
CODE1:
#include<bits/stdc++.h> using namespace std; int n,m,ans,cnt;
int a[],b[]; void dfs(int rest/*还需要摆多少盆花*/,int i/*n种花*/){
if(rest==){
ans++;ans%=;
return;
}
if(i==n+) return;
if(rest<) return;
for(int j=;j<=a[i];j++)
dfs(rest-j,i+);
return;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
dfs(m,);
cout<<ans<<endl;
}
但是非常遗憾的是暴搜显然不是正解,成功的TLE了7个点(功成身退)
所以我们想到了记忆化搜索:
SOLUTION2:(记忆化搜索)
写暴搜的原因是因为并不会正解DP,因此只好暴搜了,然后又知道暴搜妥妥的TLE,所以在暴搜代码完成之后,改成了记忆化:
大致思路还是没有变,但dfs从没有返回值变成了带有返回值的dfs,当rest==0时(形成一种摆花条件时)return 1;否则return 0(对于最小子问题);对于每一次定义一个ans(当然也可以开全局然后每次重新赋值),枚举所有的摆花盆数,ans+=dfs(rest-j,i+1)[意思是对于某种花枚举所有可能的摆放盆数,统计剩余的空位置的总方案数,表示某种花摆j盆的总方案数(可能有点不对是非常绕)],记忆化数组b[i][rest]表示第i种花摆放前剩余rest个空位置(没有摆花)剩余rest个位置摆花的方案数,当我们已经计算过这个方案数以后,就可以直接拿来用而不是总是递归炸掉了。所以加一句
if(b[i][rest]) return b[i][rest];
如何计算b[i][rest]以及每一步的ans:
其实楼上两个东西是一回事,b[i][rest]=ans;
下面来看如何计算ans:首先枚举第i种花所有摆放盆数(0~a[i]),然后dfs(rest-j,i+1),不断将求得的值加到ans里,(ans记录的是当前要摆第i种花,此时还剩rest(第i种花还没摆)个位置时所有摆花的方案数)不要忘记取mod;
最后不要忘记return ans;
CODE2:
#include<bits/stdc++.h> using namespace std; long long n,m,cnt;
long long a[],b[][];
const int mod=; long long dfs(long long rest/*还需要摆多少盆花*/,long long i/*摆放n种花*/){
if(rest==)
return ;
if(i==n+) return ;
if(rest<) return ;
if(b[i][rest]) return b[i][rest];
int ans=;
for(int j=;j<=a[i];j++){
if(rest-j<) break;
ans=(ans+dfs(rest-j,i+))%mod;
}
b[i][rest]=ans;
return ans;
} int main(){
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++)
scanf("%lld",&a[i]);
cout<<dfs(m,)%mod<<endl;
}
悄咪咪的粘上记忆化搜索的模板:(来自oi-wiki)
int g[MAXN];
int f(传入数值) {
if (g[规模] != 无效数值) return g[规模];
if (终止条件) return 最小子问题解;
g[规模] = f(缩小规模);
return g[规模];
}
int main() {
... memset(g, 无效数值, sizeof(g));
...
}
SOLUTION3:(正解-动态规划)
q姓神仙的题解【题解】
定义二维数组f[i][j]表示摆放i种花共j盆的最大方案数,初始状态是:f[i][0]=1;(因为不管是哪种花,只要不摆放,方案数均为1)这里虽然是二位数组,但DP时需要三重循环第一重循环i表示摆放i种花,第二重循环j表示这i种花共摆放多少盆(显然是1~m),第三重循环k,表示的是这种花摆放的盆数,(从0盆到a[i]盆),这里的第三层循环要从j到j-a[i]进行枚举转移方程就是f[i][j]+=f[i-1][k]%mod:
啥意思:
因为前i种花一共摆放j盆,那么假设第i种花摆放k1(k1∈(0,a[k1])盆,那么前面的i-1种花就摆放j-k1盆(所以第三层循环枚举的是前i-1种花摆放的方案数),那么所有的方案数相加就是摆放i种花j盆的最大方案数;
最后的答案就是f[n][m]%mod;(最后要%mod防止超出答案)
CODE3:
#include<bits/stdc++.h> using namespace std; int n,m;
int a[],f[][];
const int mod=; int main(){
cin>>n>>m;
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
for(int i=;i<=n;i++) f[i][]=;
for(int i=;i<=n;i++)//have n flower
for(int j=;j<=m;j++)//set out how many flower in total
for(int k=j;k>=j-a[i];k--) {//each flower set out how many
if(k<)break;
f[i][j]+=f[i-][k]%mod;
}
cout<<f[n][m]%mod;
}
真.end-
【洛谷p1077】摆花的更多相关文章
- 洛谷P1077 摆花(背包dp)
P1077 摆花 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能 ...
- 洛谷 P1077 摆花
题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...
- 洛谷P1077 摆花
题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...
- 洛谷—— P1077 摆花
https://www.luogu.org/problem/show?pid=1077 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客 ...
- 洛谷P1077 摆花——题解
题目传送 题目大意:有按顺序放的n种花,相同种类的花放一起,每种花最多放ai盆,共放了m盆花,求放花方案数. 求方案个数一般有以下思路:1.搜索:2.递推/动态规划:3.贪心:4.分治... 玄学估计 ...
- 洛谷 P1077 摆花 (背包DP)
题意:有\(n\)种花,每种花有\(a_i\)盆,现在要摆\(m\)盆花,花的种类从\([1,n]\)有序排放,问有多少种方案数. 题解:这题可以借用01背包的思路,感觉更好想一点,我们首先枚举\(n ...
- 洛谷P1077 [NOIP2012普及组]摆花 [2017年四月计划 动态规划14]
P1077 摆花 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能 ...
- 题解:洛谷P1357 花园
题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
随机推荐
- postman(二):详解在Pre-request Script中如何执行请求
一.这里以Pre-request Script标签来介绍 postman提供了postman提供了一个"Send a request"代码段,他是已经封装好的发送请求的方法 一个& ...
- LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)
LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...
- java web中乱码的种类和一些解决方式
在java web课堂测试中遇到了一些乱码问题 ,从百度上找到了许多种解决方法和乱码的种类,在这里总结一下. 一.文件出现乱码 [右击文件]->[Properties]->[Resourc ...
- SpringBoot实体类对象和json格式的转化
1.引入maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson ...
- 进度对话框QProgressDialog
继承于 QDialog import sys,time from PyQt5.QtWidgets import QApplication, QWidget,QPushButton,QProgress ...
- js基础复习~Array对象
Array对象 lenght 获取到数组的长度 concat() 方法用于合并两个或多个数组.此方法不会更改两大有数组,而是返回一个新的数组 let arr1 = ["a",&qu ...
- Python的命令行参数(argparse)
参考:https://www.cnblogs.com/lindaxin/p/7975697.html 参考:https://www.cnblogs.com/dengtou/p/8413609.html ...
- 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]
题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...
- 货币系统 Money Systems
母牛们不但创建了它们自己的政府而且选择了建立了自己的货币系统.由于它们特殊的思考方式,它们对货币的数值感到好奇. 传统地,一个货币系统是由1,,, 或 ,, 和 100的单位面值组成的. 母牛想知道有 ...
- Android 快速索引(城市列表和联系人)
最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...