线性dp(背包)、树形dp、区间dp,板子+典型问题+例题

线性dp:

01背包问题

核心板子:

for(int v=0;v<=x;v++){
    f[v] = 0;
}
//w[i]为重量,c[i]为价值,x为重量上限
for(int i=1;i<=n;i++){
    for(int v = x;v>=w[i];v--){
        f[v] = max(f[v],f[v-w[i]]+c[i]);
    }
}

01背包完整代码:

#include 
using namespace std;
typedef long long ll;

const int maxn = 100;
const int maxv = 1000;

int w[maxn],c[maxn],f[maxv];

int main(){
    int n,x;
    scanf("%d %d",&n,&x);
    for(int i=1;i<=n;i++){
        scanf("%d %d %d",&c[i],&w[i]);
    }
    for(int v=0;v<=x;v++){
        f[v] = 0;
    }
    for(int i=1;i<=n;i++){
        for(int v = x;v>=w[i];v--){
            f[v] = max(f[v],f[v-w[i]]+c[i]);
        }
    }
    int max = 0;
    for(int v=0;v<=x;v++){
        if(f[v]>max){
            max = f[v];
        }
    }
    printf("%d\n",max);
    return 0;
}

完全背包代码:

#include 
using namespace std;
typedef long long ll;

const int maxn = 100;
const int maxv = 1000;

int w[maxn],c[maxn],f[maxv];

int main(){
    int n,x;
    scanf("%d %d",&n,&x);
    for(int i=1;i<=n;i++){
        scanf("%d %d %d",&c[i],&w[i]);
    }
    for(int v=0;v<=x;v++){
        f[v] = 0;
    }
    for(int i=1;i<=n;i++){
        for(int v = w[i];v<=x;v++){
            f[v] = max(f[v],f[v-w[i]]+c[i]);
        }
    }
    int max = 0;
    for(int v=0;v<=x;v++){
        if(f[v]>max){
            max = f[v];
        }
    }
    printf("%d\n",max);
    return 0;
}

树状dp:

完整模板:

#include 
using namespace std;
typedef long long ll;

const int maxn = 6005;
int h[maxn];
int v[maxn];
vector son[maxn];
int f[maxn][2];    //f[x][0]代表以x为根的子树,x不参加的最大权值;f[x][1]代表以x为根的子树,x参加的最大权值

void dp(int x){
    f[x][0] = 0;
    f[x][1] = h[x];
    for(int i=0;i

区间dp:

核心板子:

for(int len=1;len<=m;len++){
    for(int i=1;i+len-1<=m;i++){
        int j=i+len-1;
        for(int k=i;k<=j;k++){
            f[i][j] = min(f[i][j],f[i][k-1]+f[k+1][j]+something);
        }
    }
}

完整模板:

#include 
using namespace std;
typedef long long ll;

int n,m;
int a[1001];
int f[1001][1001]; 

int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&a[i]);
    }
    sort(a+1,a+m+1);
    a[0] = 0;
    a[m+1] = n+1;
    for(int len=1;len<=m;len++){
        for(int i=1;i+len-1<=m;i++){
            int j=i+len-1;
            f[i][j] = 1000000000;
            for(int k=i;k<=j;k++){
                f[i][j] = min(f[i][j],f[i][k-1]+f[k+1][j]+a[j+1]-a[i-1]-1-1);
            }
        }
    }
    printf("%d\n",f[1][m]);
    return 0;
}

 

你可能感兴趣的:(笔记,南理工计算机专硕复试,算法,动态规划,算法)