P1077 摆花(dp&搜索)

P1077 摆花(dp&搜索)

传送门

思路: d p dp 的经典题,若没有思路先尝试爆搜,会 T T 掉,然后记忆化一下就可以 A C AC ,当然能用记忆化搜索,肯定也能 d p dp 了,最后根据别的大佬的推出来是 01 01 背包。 t q l tql

搜索代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,mod=1e6+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
inline void read(int &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
int n,m,dp[N][N],a[N];//dp[i][j]表示从第i种花开始搜,初始sum=j到达目标值(n,m)的最大方案。 
int dfs(int id,int sum){
	 if(sum>m) return 0;
	 if(id==n+1) return sum==m;
	 if(dp[id][sum]) return dp[id][sum];
	 int ans=0;
	 for(int i=0;i<=a[id];i++) ans=(ans+dfs(id+1,sum+i))%mod;
	 return dp[id][sum]=ans;
}
int main(){
	read(n),read(m);
	for(reg int i=1;i<=n;i++) read(a[i]);
	printf("%d\n",dfs(1,0));
	return 0;
}

滚动数组 d p dp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,mod=1e6+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
inline void read(int &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
int n,m,dp[2][N],a[N];
int main(){
	read(n),read(m); 
	for(int i=1;i<=n;i++)
		read(a[i]);
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=m;j++){
			dp[i%2][j]=0;//初始化使当前状态dp[i][j]保持未更新,而不是前面已有的值 比如dp[4%2][4]=dp[2%2][4] 因为下面的状态转移用到之前的dp[%2][j]在右式
			for(int k=0;k<=min(a[i],j);k++)
				dp[i%2][j]=(dp[i%2][j]+dp[(i-1)%2][j-k])%mod;
			}
	printf("%d\n",dp[n%2][m]);
	return 0;
}

01背包代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,mod=1e6+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
inline void read(int &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
int n,m,dp[N],a[N];
int main(){
	read(n),read(m); 
	for(int i=1;i<=n;i++)
		read(a[i]);
	dp[0]=1;
	for(int i=1;i<=n;i++)
		for(int j=m;j>=0;j--)
			for(int k=1;k<=min(j,a[i]);k++)//这里k从1开始 
			dp[j]=(dp[j]+dp[j-k])%mod; 
	printf("%d\n",dp[m]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106640336