先看个未经优化的二维空间dp:
#include <iostream> #include <cstdio> #include <cmath> #include <memory.h> using namespace std; const int maxn1=3500; const int maxn2=1300; int dp[maxn2][maxn2]; //int dp[maxn2]; int w[maxn1],v[maxn2]; int m,n; int max(int x,int y) { return x>y?x:y; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) cin >> w[i] >> v[i]; } memset(dp,0,sizeof(dp)); int j; for(int i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(j>=w[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]); else dp[i][j] = dp[i-1][j]; } } cout << dp[n][m] << endl; return 0; }
改进:
1。二维优化到一维
2。倒写
#include <iostream> #include <cstdio> #include <cmath> #include <memory.h> using namespace std; const int maxn1=3500; const int maxn2=13000; int dp[maxn2],w[maxn1],v[maxn2]; int m,n; int max(int a, int b) { if(a>b) return a ; else return b ; } int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); while(~scanf("%d%d",&n,&m)) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) cin >> w[i] >> v[i]; int j; for(int i=1;i<=n;i++) { for(j=m;j>=w[i];j--) { dp[j]=max(dp[j],dp[j-w[i]]+v[i]); cout << j << " j "<< dp[j]<< endl; } cout <<endl; } cout << dp[m] << endl; } return 0; }
给一组数据便于理解:
6 j 4
5 j 4
4 j 4
3 j 4
2 j 4
1 j 4
6 j 10
5 j 10
4 j 10
3 j 10
2 j 6
6 j 22
5 j 18
4 j 16
3 j 12
6 j 23
5 j 19
4 j 16
3 j 12
2 j 7
23
最后给出模板:
#include <iostream> #include <cstdio> #include <cmath> #include <memory.h> using namespace std; const int maxn1=3500; const int maxn2=13000; int dp[maxn2],w[maxn1],v[maxn1]; int m,n; int max(int a, int b) { if(a>b) return a ; else return b ; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) cin >> w[i] >> v[i]; int j; for(int i=1;i<=n;i++) for(j=m;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); cout << dp[m] << endl; } return 0; }