首页 > 代码库 > 百练 2755 神奇的口袋
百练 2755 神奇的口袋
3 20 20 20
3
枚举,最大2^20.
递归:
#include <iostream> using namespace std; int a[30]; int N; int Ways(int w ,int k ) { // 从前k种物品中选择一些,凑成体积w的做法数目 if( w == 0 ) return 1; if( k <= 0 ) return 0; return Ways(w, k -1 ) + Ways(w - a[k], k -1 ); } int main() { cin >> N; for( int i = 1;i <= N; ++ i ) cin >> a[i]; cout << Ways(40,N); return 0; }
二维动归:
#include <iostream> using namespace std; int a[30]; int N; int Ways[40][30];//Ways[i][j]表示从前j种物品里凑出体积i的方法数 int main() { cin >> N; memset(Ways,0,sizeof(Ways)); for( int i = 1;i <= N; ++ i ) { cin >> a[i]; Ways[0][i] = 1; } Ways[0][0] = 1; for( int w = 1 ; w <= 40; ++ w ) { for( int k = 1; k <= N; ++ k ) { Ways[w][k] = Ways[w][k-1]; if( w-a[k] >= 0) Ways[w][k] += Ways[w-a[k]][k-1]; } } cout << Ways[40][N]; return 0; }
数,可以考虑对值域空间-即对容积的可达性进行动态
规划。
定义一维数组 int sum[41];
依次放入物品,计算每次放入物品可达的容积,
并在相应空间设置记录,最后判断sum[40] 是否可达
,到达了几次。
优化:
#include <iostream> using namespace std; #define MAX 41 int main(){ int n,i,j,input; int sum[MAX]; for(i=0;i<MAX;i++) sum[i]=0; cin >> n; for(i=0;i<n;i++){ cin >> input; for(j=40;j>=1;j--) if(sum[j]>0 && j+input <= 40) sum[j+input] += sum[j]; //如果j有sum[j]种方式可达,则每种方式加上input就可达 j + input sum[input]++; } cout << sum[40] << endl; return 0; }对于sum[j+input] += sum[j];实际指对于所有满足sum[j]>0 && j+input <= 40在原有的sum[j+input]基础上增加sum[j],不断累积n次。另外,sum[input]++的原因是什么呢???
很容易想到sum[input]++就是存储input下标位置的值,那么为什么不能直接也和其他数一样通过sum[input] += sum[0];来得到呢,当我们把j最小设为0不是可以么?也许会有人觉得是这样,但请回头看清题意,物品的体积范围是1-40,也就是说sum[0]恒为0不会发生改变,倘若不特殊处理,那么每次input下标所对应的位置都将少1.
百练 2755 神奇的口袋
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。