其他分享
首页 > 其他分享> > 洛谷 P1077 [NOIP2012 普及组] 摆花

洛谷 P1077 [NOIP2012 普及组] 摆花

作者:互联网

题目链接:

https://www.luogu.com.cn/problem/P1077

题目大意:

放 \(m\) 盆花在一排,总共有 \(n\) 种花,编号为 \(i\) 的花最多能放 \(a[i]\) 盆,摆放时同一种花要放一起,且花的编号要从小到大。

思路:

一、暴力

直接暴力搜索得到结果,骗30分

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 105;
const int mod = 1e6 + 7;
LL n, m, a[N];
LL dfs(int k, int p){	//k为第几种花,p为几盆花 
	if (p == m) return 1;
	if (k > n || p > m) return 0;
	LL ans = 0;
	for (int i = 0; i <= a[k]; i++)
		ans = (ans + dfs(k + 1, p + i)) % mod;
	return ans;
}
int main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	cout << dfs(1, 0) << "\n";
	return 0;
}

二、记忆化搜索

暴力超时,于是想到通过记忆化减少时间,100分

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 105;
const int mod = 1e6 + 7;
LL n, m, num[N][N], a[N];
LL dfs(int k, int p){	//k为第几种花,p为几盆花 
	if (p == m) return 1;
	if (k > n || p > m) return 0;
	if (num[k][p]) return num[k][p];
	LL ans = 0;
	for (int i = 0; i <= a[k]; i++)
		ans = (ans + dfs(k + 1, p + i)) % mod;
	num[k][p] = ans;
	return ans;
}
int main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	cout << dfs(1, 0) << "\n";
	return 0;
}

三、dp

第 \(i\) 种花最多放 \(a[i]\) 盆,那么放 \(j\) 盆花的数量是前一种花从 \(j\) - \(a[i]\) 盆 到 \(j\) 盆的方案之和,即 \(f[i][j]\) = \(\sum_{k = 0}^{a[i]}f[i - 1][j - k]\)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1e6 + 7;
const int N = 105;
LL n, m, f[N][N], a[N];
int main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	f[0][0] = 1;
	for (int i = 1; i <= n; i++)
		for (int j = 0; j <= m; j++)
			for (int k = 0; k <= a[i]; k++)
				if (j >= k)
					f[i][j] = (f[i][j] + f[i - 1][j - k]) % mod;
	cout << f[n][m] % mod << "\n";
	return 0;
}

空间优化,将 \(dp\) 方程优化掉一维

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1e6 + 7;
const int N = 105;
LL n, m, f[N], a[N];
int main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	f[0] = 1;
	for (int i = 1; i <= n; i++)
		for (int j = m; j >= 0; j--)
			for (int k = 1; k <= a[i]; k++)
				if (j >= k)
					f[j] = (f[j] + f[j - k]) % mod;
	cout << f[m] % mod << "\n";
	return 0;
}

标签:摆花,洛谷,int,LL,long,return,P1077,const,mod
来源: https://www.cnblogs.com/Hamine/p/15686826.html