zoukankan      html  css  js  c++  java
  • 区间DP

    区间DP

    https://oi-wiki.org/dp/interval/

    例1:石子合并

    破环成链

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=205;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n,sum[N][N],a[N];
    int f[N][N],g[N][N];//f -min g -max
    inline void Max(int &x,int y){if(x<y)x=y;}
    inline void Min(int &x,int y){if(x>y)x=y;}
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) 
    		a[i+n]=a[i]=read();	
    	for(int i=1;i<=2*n;i++)
    		for(int j=i;j<=2*n;j++)
    			for(int k=i;k<=j;k++)
    				sum[i][j]+=a[k];
    	for(int len=1;len<=n;len++)
    		for(int l=1;l<(n<<1)&&l+len<(n<<1);l++) {
    			int r=l+len;
    			f[l][r]=0x3f3f3f3f;
    			for(int k=l;k<r;k++) {
    				f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+sum[l][r]);
    				g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+sum[l][r]);
    			}
    		}
    	int ans1=0x3f3f3f3f,ans2=0;
    	for(int i=1;i<=n;i++) {
    		Min(ans1,f[i][i+n-1]);
    		Max(ans2,g[i][i+n-1]);
    	}
    	printf("%d
    %d
    ",ans1,ans2); 
    	return 0;
    }
    

    例2:Polygon多边形

    #include<bits/stdc++.h>
    const int inf=0x3f3f3f3f;
    int n,ans=-inf;
    int a[105];
    int f[150][150],g[150][150];
    char c[105];
    int min(int x,int y){
        return x>y?y:x;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    int main(){
        scanf("%d
    ",&n);
        for(int i=1;i<=n;i++){
            scanf("%c %d",&c[i],&a[i]);getchar();
            a[n+i]=a[i];c[n+i]=c[i];
        }
        for(int i=1;i<=(n<<1);i++)
            for(int j=1;j<=(n<<1);j++)
                f[i][j]=-inf,g[i][j]=inf;
    
        for(int i=1;i<=(n<<1);i++)
            f[i][i]=g[i][i]=a[i];
    
        for(int len=2;len<=n;len++){
            for(int i=1,j=len;j<=(n<<1);i++,j++){
                for(int k=i;k<j;k++){
                    if(c[k+1]=='x'){
                        f[i][j]=max(f[i][j],max(f[i][k]*f[k+1][j],max(g[i][k]*g[k+1][j],max(f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]))));
                        g[i][j]=min(g[i][j],min(f[i][k]*f[k+1][j],min(g[i][k]*g[k+1][j],min(f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]))));
                    }
                    else if(c[k+1]=='t'){
                        f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
                        g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]);
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
            ans=max(ans,f[i][i+n-1]);
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++)
            if(f[i][i+n-1]==ans)
                printf("%d ",i);
        return 0;
    }
    

    例3:能量项链

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=205;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n;
    ll f[N][N],ans,a[N];
    inline void Max(ll &x,ll y){if(x<y)x=y;}
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) 
    		a[i+n]=a[i]=read();	
    	
    	for(int len=1;len<=n;len++)
    		for(int l=1;l<=(n<<1)&&l+len<=(n<<1);l++) {
    			int r=l+len;
    			for(int k=l+1;k<=r;k++) 
    				Max(f[l][r],f[l][k-1]+f[k][r]+a[l]*a[r+1]*a[k]);
    		}
    	for(int i=1;i<=n;i++) 
    		Max(ans,f[i][i+n-1]);
    	printf("%lld
    ",ans); 
    	return 0;
    }
    

    例4:金字塔

    dfs序的性质,

    ([l,k]) 是一棵子树,则 (l)(k) 为根节点,即(s[l]=s[k])

    $ dp[l][r]=dp[l][r]+dp[l+1][k-1]*dp[k][r] $

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=305;
    const int P=1e9;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n;
    char s[305];
    ll f[N][N];
    int main() {
        scanf("%s",s+1);
        n=strlen(s+1);
        for(int i=1;i<=n;i++) f[i][i]=1;
        for(int len=1;len<=n;len++)
        	for(int l=1;l<=n;l++) {
        		int r=l+len;
        		if(r>n) break;
        		for(int k=l+2;k<=r;k++) 
        			if(s[k]==s[l])
        				f[l][r]=(f[l][r]+f[l+1][k-1]*f[k][r]%P)%P;
    		}
        printf("%lld
    ",f[1][n]);
    	return 0;
    }
    

    例5:Treats for the Cows G/S

    (r-l+第几天卖出=n)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=2055;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n;
    int f[N][N],ans,a[N];
    inline void Max(int &x,int y){if(x<y)x=y;}
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) {
    		a[i]=read();
    		f[i][i]=a[i]*n;
    	}
    	for(int len=1;len<=n;len++)	
    		for(int l=1;l<=n;l++) {
    			int r=l+len;
    			if(r>n) break;
    			if(l==r) f[l][r]=a[l]*n;
    			else {
    				Max(f[l][r],f[l+1][r]+(n-r+l)*a[l]);
    				Max(f[l][r],f[l][r-1]+(n-r+l)*a[r]);
    			}
    		}
    	printf("%d
    ",f[1][n]); 
    	return 0;
    }
    
  • 相关阅读:
    Less 文档查看心得
    Jquery+SlideDown+在IE7和IE6中的bug
    Highcharts 图表库
    安卓 日常问题 工作日志6
    安卓 日常问题 工作日志5
    安卓 日常问题 工作日志 3
    安卓 日常问题 工作日志 2
    安卓 日常问题 工作日志
    新的开始 安卓工程师
    2018.4.16号 我也不知道应该写点什么
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13507922.html
Copyright © 2011-2022 走看看