大白第一章第四节dp例题

入口

UVALive - 3882 

#include<cstdio>
using namespace std;
const int N=1e4+5;
int n,m,k,f[N];
int main(){
    //f[i]表示第i次要删的数字 
    while(scanf("%d%d%d",&n,&k,&m)==3&&n){
        //1
        //f[1]=0;
        //for(int i=2;i<=n;i++) f[i]=(f[i-1]+k)%i;
        //int ans=(m-k+f[n]+1)%n;
        //2
        //int s=0;
        //for(int i=2;i<=n;i++) s=(s+k)%i;
        //int ans=(m-k+s+1)%n;//这3句话来源于上面 
        //if(ans<=0) ans+=n;
        //printf("%d
",ans);
        //3
        int s=0;
        for(int i=2;i<n;i++) s=(s+k)%i;
        s=(s+m)%n;
        printf("%d
",s+1);
    }
    return 0;
}

UVA - 10635 

//turn to lis
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int T,cas=1,n,p,q,pa[N],a[N],b[N],c[N];
inline void LIS(){
    int len;c[len=1]=b[1];
    for(int i=2,pos;i<=q+1;i++){
        if(b[i]>c[len]) c[++len]=b[i];
        else{
            pos=lower_bound(c+1,c+len+1,b[i])-c;
            c[pos]=b[i];
        }
    }
    printf("Case %d: %d
",cas,len);
}
int main(){
    for(scanf("%d",&T);cas<=T;cas++){
        scanf("%d%d%d",&n,&p,&q);
        for(int i=1;i<=p+1;i++) scanf("%d",&a[i]),pa[a[i]]=i;
        for(int i=1;i<=q+1;i++) scanf("%d",&b[i]),b[i]=pa[b[i]];
        LIS();
    }
    return 0;
} 
/*//lcs->TLE 
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+5;
int T,cas=1,n,p,q,a[N],b[N],f[2][N*10];
int main(){
    for(scanf("%d",&T);cas<=T;cas++){
        scanf("%d%d%d",&n,&p,&q);
        for(int i=1;i<=p+1;i++) scanf("%d",&a[i]);
        for(int i=1;i<=q+1;i++) scanf("%d",&b[i]);
        memset(f,0,sizeof f);int now=0;
        for(int i=1;i<=p+1;i++){
            now^=1;
            for(int j=1;j<=q+1;j++){
                if(a[i]==b[j]) f[now][j]=f[now^1][j-1]+1;
                else f[now][j]=max(f[now][j-1],f[now^1][j]);
            }
        }
        printf("Case %d:%d
",cas,f[now][q+1]);
    }
    return 0;
} */

UVA - 10891 

//朴素(AC)
#include<cstdio>
#include<cstring>
//dp(i,j)表示选择[i,j]的子序列,在双方都采取最优策略,先手得分的最大值
//dp(i,j)=sum(i,j)-min{d(i+1,j)……d(j,j),d(i,j-1)……d(i,i)} 
#include<algorithm>
using namespace std;
const int N=105;
int n,s[N],f[N][N];
bool vis[N][N];
int dp(int x,int y){
    if(vis[x][y]) return f[x][y];
    vis[x][y]=1;
    int m=0;//全部取光(精髓) 
    for(int i=x+1;i<=y;i++) m=min(m,dp(i,y));
    for(int i=x;i<y;i++) m=min(m,dp(x,i));
    return f[x][y]=s[y]-s[x-1]-m;
}
int main(){
    while(scanf("%d",&n)==1&&n){
        for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i]+=s[i-1];
        memset(vis,0,sizeof vis);
        printf("%d
",2*dp(1,n)-s[n]);
    }
    return 0;
} 
//辅助数组优化
//f(i,j)=min{d(i,j),d(i+1,j)……d(j,j)}
//g(i,j)=min{d(i,j),d(i,j-1)……d(i,i)}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105;
int n,a[N],s[N],f[N][N],g[N][N],dp[N][N];
int main(){
    while(scanf("%d",&n)==1&&n){
        memset(f,0,sizeof f);
        memset(g,0,sizeof g);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i][i]=g[i][i]=dp[i][i]=a[i];
        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
        for(int L=1;L<n;L++){
            for(int i=1;i+L<=n;i++){
                int j=i+L;
                int m=0;
                m=min(m,f[i+1][j]);
                m=min(m,g[i][j-1]);
                dp[i][j]=s[j]-s[i-1]-m;
                f[i][j]=min(dp[i][j],f[i+1][j]);
                g[i][j]=min(dp[i][j],g[i][j-1]);
            }
        }
        printf("%d
",2*dp[1][n]-s[n]);
    }
    return 0;
} 

UVA - 11825 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1<<17;
int n,cas;
int p[N],cover[N],f[N];
int main(){
    while(scanf("%d",&n)==1&&n){
        memset(p,0,sizeof p);
        memset(cover,0,sizeof cover);
        for(int i=0,m,x;i<n;i++){
            scanf("%d",&m);
            p[i]=1<<i;
            while(m--) scanf("%d",&x),p[i]|=(1<<x);
        }
        for(int S=0;S<(1<<n);S++){
            cover[S]=0;
            for(int i=0;i<n;i++) if(S&(1<<i)) cover[S]|=p[i];
        }
        //dp transfer equation:
        //f(S)=max{f(S-S0)|S0 belong to S,and cover[S0]==ALL}
        int ALL=(1<<n)-1;f[0]=0;
        for(int S=1;S<(1<<n);S++){
            f[S]=0;
            for(int S0=S;S0;S0=(S0-1)&S){
                if(cover[S0]==ALL) f[S]=max(f[S],f[S^S0]+1);
            }
        }
        printf("Case %d: %d
",++cas,f[ALL]);
    }
    return 0;
}

UVA - 10859 

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=1005;
const int M=2000;
int n,m,T,f[N][N];bool vis[N][N];
vector<int>graph[N];
int dp(int i,int j,int fa){
    if(vis[i][j]) return f[i][j];
    vis[i][j]=1;
    int &ans=f[i][j];
    ans=M;
    //1:now point with light
    for(int k=0;k<graph[i].size();k++){
        if(graph[i][k]!=fa){
            ans+=dp(graph[i][k],1,i);
        }
    }
    if(!j&&fa>=0) ans++;//not root
    if(j||fa<0){
    //2:now point without light
        int sum=0;
        for(int k=0;k<graph[i].size();k++){
            if(graph[i][k]!=fa){
                sum+=dp(graph[i][k],0,i);
            }
        }
        if(fa>=0) sum++;//not root
        ans=min(ans,sum);
    }
    return ans;
}
int main(){
    for(scanf("%d",&T);T--;){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) graph[i].clear();
        for(int i=0,x,y;i<m;i++){
            scanf("%d%d",&x,&y);
            graph[x].push_back(y);
            graph[y].push_back(x);
        }
        memset(vis,0,sizeof vis);
        int ans=0;
        for(int i=0;i<n;i++){
            if(!vis[i][0]){
                ans+=dp(i,0,-1);
            }
        }
        //ans=Ma+b;beacause DAG
        printf("%d %d %d
",ans/M,m-ans%M,ans%M);
    }
    return 0;
}

UVALive - 3983 

#include<cstdio>
using namespace std;
const int N=1e5+5;
int T,c,n,x[N],y[N];
int dist2origin[N],total_dist[N],total_wight[N];
int q[N],f[N];
inline int ABS(int x){
    return x>0?x:-x;
}
//dp[i]=min{dp[j]+dist2origin[j+1]+dist[j+1,i]+dist2origin[i]|j<=i,w[j+1,i]<=c}
//==>min{dp[j]+dist2origin[j+1]-total_dist[j+1]}+total_dist[i]+dist2origin[i]
//        (let total_dist[i]=w1+w2+……+wi,then dist[j+1,i]=total_dist[i]-total_dist[j+1])
//==>min{func(j)}+total_dist[i]+dist2origin[i];
//        (let func(j)=dp[j]+dist2origin[j+1]-total_dist[j+1])
//use humdrum queue to optimize time.(finised)
inline int func(int j){
    return f[j]+dist2origin[j+1]-total_dist[j+1];
}
int main(){
    for(scanf("%d",&T);T--;){
        scanf("%d%d",&c,&n);
        dist2origin[0]=total_dist[0]=total_wight[0]=x[0]=y[0]=0;
        for(int i=1,w;i<=n;i++){
            scanf("%d%d%d",&x[i],&y[i],&w);
            dist2origin[i]=ABS(x[i])+ABS(y[i]);
            total_dist[i]=total_dist[i-1]+ABS(x[i]-x[i-1])+ABS(y[i]-y[i-1]);
            total_wight[i]=total_wight[i-1]+w;
        }
        int h=0,t=0;
        for(int i=1;i<=n;i++){
            for(;h<t&&total_wight[i]-total_wight[q[h]]>c;h++);
            f[i]=func(q[h])+total_dist[i]+dist2origin[i];
            for(;h<t&&func(i)<=func(q[t]);t--);
            q[++t]=i;
        }
        printf("%d
",f[n]);
        if(T>0) putchar('
');
    }
    return 0;
}

UVALive - 4794 

//dp transfer equation:
//dp(r,c,S)
//1 dp(r0,c,S0)=dp(r-r0,c,S-S0){1<=r0<r}
//2 dp(r,c0,S0)=dp(r,c-c0,S-S0){1<=c0<c}
//3 dp(r,c,S)=dp(c,r,S)
//use g(r,S) take place of dp(r,c,S){r<=c}, and judge whether is legal or not.
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=16,M=105;
int T,n,cas,x,y,a[N],sum[1<<N];
bool f[1<<N][M],vis[1<<N][M];
int bitcount(int x){
    return !x?0:bitcount(x>>1)+(x&1);
}
bool dp(int S,int x){
    if(vis[S][x]) return f[S][x];
    vis[S][x]=1;
    bool &ans=f[S][x];
    if(bitcount(S)==1) return ans=1;
    int y=sum[S]/x;
    for(int S0=(S-1)&S;S0;S0=(S0-1)&S){
        int S1=S-S0;
        if(!(sum[S0]%x)&&dp(S0,min(x,sum[S0]/x))&&dp(S1,min(x,sum[S1]/x))) return ans=1;
        if(!(sum[S0]%y)&&dp(S0,min(y,sum[S0]/y))&&dp(S1,min(y,sum[S1]/y))) return ans=1;
    }
    return ans=0;
}
int main(){
    while(scanf("%d",&n)==1&&n){
        scanf("%d%d",&x,&y);
        memset(vis,0,sizeof vis);
        memset(f,0,sizeof f);
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        for(int S=1;S<(1<<n);S++){
            sum[S]=0;
            for(int i=0;i<n;i++){
                if(S&(1<<i)) sum[S]+=a[i];
            }
        }
        int ALL=(1<<n)-1;bool ans;
        if(sum[ALL]!=x*y||sum[ALL]%x) ans=0;
        else ans=dp(ALL,min(x,y));
        printf("Case %d: %s
",++cas,ans?"Yes":"No");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/6392677.html