题外废话:

真的超级喜欢这道题


摆花【题目链接】

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】摆花的更多相关文章

  1. 洛谷P1077 摆花(背包dp)

    P1077 摆花 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能 ...

  2. 洛谷 P1077 摆花

    题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...

  3. 洛谷P1077 摆花

    题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...

  4. 洛谷—— P1077 摆花

    https://www.luogu.org/problem/show?pid=1077 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客 ...

  5. 洛谷P1077 摆花——题解

    题目传送 题目大意:有按顺序放的n种花,相同种类的花放一起,每种花最多放ai盆,共放了m盆花,求放花方案数. 求方案个数一般有以下思路:1.搜索:2.递推/动态规划:3.贪心:4.分治... 玄学估计 ...

  6. 洛谷 P1077 摆花 (背包DP)

    题意:有\(n\)种花,每种花有\(a_i\)盆,现在要摆\(m\)盆花,花的种类从\([1,n]\)有序排放,问有多少种方案数. 题解:这题可以借用01背包的思路,感觉更好想一点,我们首先枚举\(n ...

  7. 洛谷P1077 [NOIP2012普及组]摆花 [2017年四月计划 动态规划14]

    P1077 摆花 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能 ...

  8. 题解:洛谷P1357 花园

    题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. DDD领域驱动设计初探(七):Web层的搭建

    前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DDD领域驱动设计初 ...

  2. 外网无法ping自己的linux服务器

    Linux默认是允许Ping响应的,系统是否允许Ping由2个因素决定的:A.内核参数,B.防火墙,需要2个因素同时允许才能允许Ping,2个因素有任意一个禁Ping就无法Ping. 具体的配置方法如 ...

  3. 关于CSS你应该知道的基础知识 - 盒模型篇

    浏览器渲染引擎通过盒模型的方式来布局html元素.我们可以将每一个html元素都看做是一个盒子,每一个盒子都有长和款,多个这样的盒子组成了我们的网页. Margin,Border,Padding 每一 ...

  4. java8 时间日期操作包总结

  5. java.lang.Void类源码解析_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 在一次源码查看ThreadGroup的时候,看到一段代码,为以下: /* * @throws NullPointerEx ...

  6. hadoop2.7伪分布式搭建

    0.配置主机名 hostnamectl set-hostname spark1 1.上传hadoop-2.7.1.tar.gz文件并解压 tar -xvf hadoop-2.7.1.tar.gz 2. ...

  7. Quantitative Strategies for Achieving Alpha(一)

    1. 怎么构建测试 所有的测试五等分,表明我们的回测的universe被分为五个组,根据我们要测试的公司因子的值. Quintiles provide a clear answer to that q ...

  8. Quick BI支持哪些数据源(配置操作篇)

    Quick BI 潜心打造了核心技术底座(OLAP分析引擎),实现了SQL解析.SQL调度.SQL优化.查询加速等基础能力,支撑Quick BI的数据分析和查询加速.OLAP分析引擎包括数据源连接.数 ...

  9. 5.React中组件通信问题

    1.父组件传递值给子组件 想必这种大家都是知道的吧!都想到了用我们react中的props,那么我在这简单的写了小demo,请看父组件 class Parent extends Component{ ...

  10. django搭建一个小型的服务器运维网站

    前言   不管是运维还是开发抑或是测试,工作中不免会和Linux服务器打交道,常见的操作譬如:查看CPU或内存状态.查看和修改服务器时间.查看或者修改服务器配置文件.实时查看或回看系统的日志.重启服务 ...