码迷,mamicode.com
首页 > 其他好文 > 详细

TYVJ1096

时间:2014-08-24 23:33:53      阅读:350      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   os   io   for   div   代码   log   

也不知道属于什么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

标签:style   blog   color   os   io   for   div   代码   log   

原文地址:http://www.cnblogs.com/GJKACAC/p/3933669.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!