P1077 摆花(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[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;
}
滚动数组 。
#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;
}