方法一:最朴素方法,不优化时间和空间
空间和时间复杂度都是O(n*s),n为奶牛数目,s为奶牛高度之和
代码:照理说,空间复杂度超过限制,但是POJ居然通过了
#include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; int n; //# of cows int b; //height of shelf int h[21]; //heights of cows int s; //sum of cow's heights //DP bool dp[21][20000001]; //dp[i][j]: cow[1...i] considered, whether stack height of j exists //DP(0-1背包) void solve(){ //DP(0-1背包) init int i,j; dp[0][0]=true; for(j=1;j<=s;j++) dp[0][j]=false; //DP(0-1背包) for(i=1;i<=n;i++){//依次考虑到cow[1...i] for(j=0;j<=s;j++){ dp[i][j]=dp[i-1][j]; if(j-h[i]>=0){ dp[i][j]=dp[i][j] || dp[i-1][j-h[i]]; } } } } int main(){ //input scanf("%d%d",&n,&b); int i; s=0; for(i=1;i<=n;i++){ scanf("%d",&h[i]); s+=h[i]; } //DP(0-1背包) solve(); //output for(i=b;i<=s;i++){ if(dp[n][i]==true){ printf("%d\n",i-b); break; } } system("pause"); return 0; }
方法二:优化空间
用一维数组代替二维数组求解DP问题时,内部循环j必须递减循环,∵
dp[i][j]=dp[i-1][j] || dp[i-1][j-h[i]],递减循环j保证在求dp[i][j]的时候dp[i-1][j-h[i]]还是修改前的值(而非修改后的值dp[i][j-h[i])!
//DP(0-1背包) for(i=1;i<=n;i++){ for(j=s;j>=0;j--){ //dp[j]=dp[j]; if(j-h[i]>=0){ dp[j]=dp[j] || dp[j-h[i]]; } } }
代码:
#include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; int n; int b; int h[21]; int s; //DP bool dp[20000001]; //dp[21][20000001] //DP(0-1背包) void solve(){ //DP(0-1背包) init int i,j; dp[0]=true; for(j=1;j<=s;j++) dp[j]=false; //DP(0-1背包) for(i=1;i<=n;i++){ for(j=s;j>=0;j--){ //dp[j]=dp[j]; if(j-h[i]>=0){ dp[j]=dp[j] || dp[j-h[i]]; } } } } int main(){ //input scanf("%d%d",&n,&b); int i; s=0; for(i=1;i<=n;i++){ scanf("%d",&h[i]); s+=h[i]; } //DP(0-1背包) solve(); //output for(i=b;i<=s;i++){ if(dp[i]==true){ //if(dp[n][i]==true){ printf("%d\n",i-b); break; } } system("pause"); return 0; }