今天发现了一道非常棒的题,先上链接
https://www.luogu.com.cn/problem/P1077
这个题棒就棒在不仅可以用搜索(必须得是记忆化搜索,单纯的搜索会超时)来做,还可以用动态规划来做,还可以用01背包解决,还可以用前缀和优化和数学知识解决,由于我还涉世(suan fa)未深,所以只对记忆化搜索、动态规划和01背包进行了研究。
昨天做这道题的时候我最先想到的是动态规划,花费了将近一小时研究,虽然和答案很像了,但是还是没AC…
先说说动态规划的方法吧,dp[i][j]表示前i种花摆j盆有多少种方法,动态转移方程为 dp[i][j]=dp[i][j]+dp[i-1][j-k] 由于要取1000007的模,为了避免超出int类型范围,所以这里要加一个取余运算
dp[i][j]=(dp[i][j]+dp[i-1][j-k])%1000007;
意思为:前i种花摆j盆的方法等于前i-1种花摆[j-m,j]盆花的方法和,其中m为min(j,a[i]),即取第i种花最多可摆的数目和可摆花数目的最小值,其实很好理解,但是不太好解释…只能是多做题才能悟出来吧…我昨天就是栽在这里了…
然后要进行初始化,根据事实,如果可摆的花数目为0的时候,则全置为1
for(int i=0;i<=n;i++){
dp[i][0]=1;
}
最后输出dp[n][m]就是结果了
动态规划AC代码:
#include <iostream>
using namespace std;
#define N 1000007
int n,m,a[105];
long long dp[105][105];
int main(