方法一:最朴素方法,不优化时间和空间
空间和时间复杂度都是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;
}