首页 > 代码库 > TYVJ1096
TYVJ1096
也不知道属于什么DP,反正就是DP算了。。
设dp[i][j]表示前i个数组合成j的最多方案数和恰好装满的01背包类似
一开始的思路是dp[i][j]=dp[i-1][j-a[i]]+1;真不知道当时是怎么能想出这个方程来的,或许是看到长得不错就要它了吧。。
后来敲代码,怎么调都对不了,后来就反思,老觉得少点东西,
原来它在这里:对于dp[i][j]来说,有两种从i-1的转移过来的方式 :
一种是组合中没有a[i]的,即由前i-1个数组成j,dp[i-1][j] 另一种是组合中包含a[i]的(虽说包含,但是这种组合的方案数可能为0),即由前i-1个数组成j-a[i]的方案数转移过来
状态方程:
|dp[i-1][j] j<a[i]
dp[i][j] = |
|dp[i-1][j]+dp[i-1][j-a[i]] j>=a[i]
边界条件:(根据个人的思考方式来理解来找边界)因为是根据i一层一层的向上推所以i最小的时候的那一层需要求出,这也很简单i=1时只有dp[1][a[1]]=1;别的都是0 另外会出现dp[i-1][j-a[i]],这里的j-a[i]可能为0所以需要把竖着的边界也求出,这个也很好求,不管前几个数都不可能组合出0,所以dp[i][0] = 1;(i>=1)
今天五题的最后一个了,终于完了,该睡了。。。。啊喔啊喔~~
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 10005; 7 int a[105],dp[101][maxn]; 8 int main() 9 {10 int n,m;11 while(cin>>n>>m)12 {13 for(int i = 1;i<=n;++i)scanf("%d",a+i);14 //sort(a+1,a+1+n);15 memset(dp,0,sizeof(dp));16 dp[1][a[1]] = 1;17 for(int i = 1;i<=n;++i)dp[i][0] = 1;18 for(int i = 2;i<=n;++i)19 for(int j = 1;j<=m;++j)20 if(j>=a[i])dp[i][j] = dp[i-1][j]+dp[i-1][j-a[i]];21 else dp[i][j] = dp[i-1][j];22 // for(int i = 1;i<=n;++i)23 // {24 // for(int j = 1;j<=n;++j)25 // printf("%d ",dp[i][j]);26 // printf("\n");27 // }28 printf("%d\n",dp[n][m]);29 }30 return 0;31 }
TYVJ1096
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。