http://codevs.cn/problem/1068/

我的思路是由len推导len+1层。

因为计算m个卡片最大值,需要知道m-1个卡片的最大值。(不知道网上其他人的算法是怎么理解的,感觉自己的算法很耗时间)

#include<iostream>
using namespace std;
int dp[41][41][41][41];
int a[351]; 
int n,m,t;
int mi=0,mj=0,mk=0,ml=0;
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int mt=m;
	while(mt--){
		cin>>t;
		if(t==1){
			++mi;
		}else if(t==2){
			++mj;
		}else if(t==3){
			++mk;
		}else if(t==4){
			++ml;
		}
	}
	for(int len=0;len<=m;len++){
	//	cout<<"-----------------------"<<endl;
	//	cout<<"len="<<len<<endl;
		for(int i=0;i<=len&&i<=mi;i++){
			for(int j=0;j+i<=len&&j<=mj;j++){
				for(int k=0;i+j+k<=len&&k<=mk;k++){
					int l=len-i-j-k;
					if(l>ml)continue;
				//	cout<<i<<" ";cout<<j<<" ";cout<<k<<" ";cout<<l<<" ";
				//	cout<<dp[i][j][k][l]<<endl;
					int num=i*1+j*2+k*3+l*4+1;					
					if(num+1<=n)dp[i+1][j][k][l]=max(dp[i+1][j][k][l],dp[i][j][k][l]+a[num+1]);
					if(num+2<=n)dp[i][j+1][k][l]=max(dp[i][j+1][k][l],dp[i][j][k][l]+a[num+2]);
					if(num+3<=n)dp[i][j][k+1][l]=max(dp[i][j][k+1][l],dp[i][j][k][l]+a[num+3]);
					if(num+4<=n)dp[i][j][k][l+1]=max(dp[i][j][k][l+1],dp[i][j][k][l]+a[num+4]);
					
				}
			}
		}		
	}
//	for(int i=0;i<=mi;i++){
//		for(int j=0;j<=mj;j++){
//			for(int k=0;k<=mk;k++){
//				for(int l=0;l<=ml;l++){
//					cout<<
//				}
//			}
//		}
//	}
	cout<<dp[mi][mj][mk][ml]+a[1]<<endl;
	return 0;
}