基础DP

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

int DP[123][222];

int main(){
//01背包 递推1
//从第i个中挑选总重量不超过j的最大价值物品 dp[n][j]=0 dp[i][j] = max (dp[i+1][j],dp[i+1][j-wi]+vi) / dp[i+1][j]
//从前i个中挑选。。。。。。。。。。。。。  dp[0][j]=0 dp[i][j] = max (dp[i-1][j],dp[i-1][j-wi]+vi) / ..........
	//dp[n]维memset 
	for(int i = n; i >= 1; i--){ // 
		for(int j = 0; j <= W; j++){
			if(j-w[i] >= 0)
				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[1][W]; 
	//dp[1]初始化 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= W; j++){
			if(j-w[i] >= 0)
				dp[i+1][j] = max(dp[i][j],dp[i][j-w[i]]+v[i]);
			else
				dp[i+1][j] = dp[i][j];
		}
	}
	cout << dp[n+1][W];
//状态转移:从前i个中挑选总重量不超过j的最大价值物品转移到从前i+1中挑选...不超过j 和 不超过j+w[i]的状态 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= W; j++){
			dp[i+1][j] = max(dp[i+1][j],dp[i][j]);
			if(j+w[i] <= W){
				dp[i+1][j+w[i]] = max(dp[i+1][j],dp[i+1][j+w[i]]+v[i]);
			}
		}
	}
	cout << dp[1][W];
//完全背包:前i个的取法:dp[i][j] = max(dp[i-1][j],dp[i][j-w[i]]+v[i]) /dp[i-1][j] 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= W; j++){
			if(j-w[i] >= 0)
				dp[i+1][j] = max(dp[i][j],dp[i+1][j-w[i]]+v[i]); 
			else
				dp[i+1][j] = dp[i][j];
		}
	}
//一维DP的01背包: 
	for(int i = 1; i <= n; i++){
		for(int j = W; j >= w[i]; j--){
			dp[j] = max(dp[j],dp[j-w[i]]+v[i]); 
		}
	}
	cout << dp[W];
//一维DP的完全背包:
	for(int i = 1; i <= n; i++){ //下标[1...n] 
		for(int j = w[i]; j <= W; j++){
			dp[j] = max(dp[j],dp[j-w[i]]+v[i]); 
		}
	} 
	cout << dp[W]; 
//O(nlogn)的LIS问题:
//dp 0x3f3f3f3f初始化 
	for(int i = 1;i <= n ;i++){
		*lower_bound(dp+1,dp+n+1,a[i]) = a[i]; 
	} 
	cout << lower_bound(dp+1,dp+n+1,INF)-(dp+1) << endl; 
}
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
//int dp[]


int dfs(int cur,int W){
	if(cur==n+1) return 0;
	if(W<w[cur]) return dfs(cur+1,W);
	return max(dfs(cur+1,W),dfs(cur+1,W-w[cur])+v[cur]); 
} 

int DP(int cur,int W){
	if(cur==n+1) return dp[cur][W] = 0; //这里也要记忆 
	if(dp[cur][W]!=-1) return dp[cur][W];
	if(W<w[cur]) return dp[cur][W] = DP(cur+1,W);
	return dp[cur][W] = max(DP(cur+1,W),DP(cur+1,W-w[cur])+v[cur]);
}

int main(){
	//input init->0 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= W; j++){ //向背包容量的状态转移 
			if(j-w[i] < 0) dp[i][j] = dp[i+1][j];
			else dp[i][j] = max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]); 
		}
	}
	cout << dp[n][W] << endl; 
} 

int main(){
	//input init->0 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= W; j++){ //压缩 
			if(j-w[i] < 0) dp[i&1][j] = dp[(i+1)&1][j];
			else dp[i&1][j] = max(dp[(i+1)&1][j],dp[(i+1)&1][j-w[i]]+v[i]); 
		}
	}
	cout << dp[n&1][W] << endl; 
} 

int main(){
	//init dp[0]=0
	for(int i = 1; i <= n; i++){
		for(int j = W; j >= w[i]; j--){
			dp[j] = max(dp[j],dp[j-w[i]]+v[i]); //每次只需知道上面的和左上面的 
		}
	}
	cout << dp[W] << endl;
}

//ComPack

经典题目
https://people.cs.clemson.edu/~bcdean/dp_practice/

树形DP

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 1e3;
typedef vector<int> vi;

int level[maxn],parent[maxn];
vi G[maxn];
int sumC[maxn],sumS[maxn]; //孩子 孙子和 
int dp[maxn];
int maxLevel; 
//dp[i] =  //d[i]表示以i为根的子树的最大独立集 di = max(sum of d son of i , 1+ sum of grandson of i) 


void dfs(int u,int fa){ //更新level与parent 
	if(fa==-1)
		level[u] = 0;
	else
		level[u] = level[fa]+1;
	if(level[u] > maxLevel)
		maxLevel = level[u];
	for(int i = 0; i < G[u].size(); i++){
		int v = G[u][i];
		if(v != fa) dfs(v,parent[v]=u);
	}
}


int rootDP(int u){
	parent[u] = -1;
	maxLevel = -1;
	dfs(u,p[u]); //建树 
	for(int i = maxLevel, i >= 0; i--){
		for(int j = 0; j < V; j++){
			if(level[j]==i){ // 一开始j是叶子节点 
				dp[j] = max(sumS[j]+1,sumC[j]);
				if(i-1>=0) //刷表法 
					sumC[p[j]]+=dp[j];
				if(i-2>=0)
					sumS[p[p[j]]]+=dp[j];
			}
		}
	}
	return dp[u]; 
} 

int main(){
	int T,u,v; scanf("%d",&T);
	while(T--){
		int V; scanf("%d",&V);
		for(int i = 0; i < V-1; i++){
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		int best = -1;
		for(int i = 0; i < V; i++){
			memset(sumC,0,sizeof sumC);
			memset(sumS,0,sizeof sumS);
			int temp = rootDP(i);
			if(temp > best) best = temp;
		}
		printf("%d\n",best);
	}
	return 0;
}
posted @ 2017-07-23 19:38  Caturra  阅读(168)  评论(0)    收藏  举报