普通dp总结

传纸条

 

从(1,1)传纸条到(m,n),经过后返回时不能经过

 

四维dp,f[i][j][k][p]表示从(i,j)到(k,p)的答案,显然

f[i][j][k][p]=max(f[i-1][j][k-1][p],max(f[i-1][j][k][p-1],max(f[i][j-1][k-1][p],f[i][j-1][k][p-1])))+a[i][j]+a[k][p]

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=55;
inline int read(){
    int x=0,k=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return k*x;
}
int a[maxn][maxn],f[maxn][maxn][maxn][maxn];
int main(){
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    int n,m;
    n=read();m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=n;k++)
                for(int p=j+1;p<=m;p++){
                    f[i][j][k][p]=max(f[i-1][j][k-1][p],max(f[i-1][j][k][p-1],max(f[i][j-1][k-1][p],f[i][j-1][k][p-1])))+a[i][j]+a[k][p];
                }
    cout<<f[n][m-1][n-1][m];
    return 0;
}
View Code

 

 

扫雷

 

两列扫雷方格,给第二列数字,问第一列有几种可能

 

本来是dp的但是太水了,最多的情况是第一个是1,则最多有2种,在依次判断一下,不符合的减去就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=10005;
inline int read(){
    int x=0,k=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return k*x;
}
int a[maxn],b[maxn],ans=2;
void pd(int n){
    for(int i=2;i<=n+1;i++){
        b[i]=a[i-1]-b[i-1]-b[i-2];
        if(b[i]!=1&&b[i]!=0){
            ans--;
            break;
        }
        if(i==n+1&&b[i]!=0) ans--;
    }
}
int main(){
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    int n;
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    b[1]=0;pd(n);
    b[1]=1;pd(n);
    cout<<ans;
    return 0;
}
View Code

 

 

数列_NOI导刊2010提高(06)

 

一串数,擦去一些,问a[i]=i的最多有多少

 

f[i][j]表示前i个数有j个数保留的答案,则若a[i]=j时,满足条件,则f[i][j]=max(f[i-1][j],f[i-1][j-1]+1),否则f[i][j]=max(f[i-1][j],f[i-1][j-1])

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1005;
inline int read(){
    int x=0,k=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return k*x;
}
int f[maxn][maxn],a[maxn];
int main(){
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    int n,ans=0;
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++)
        for(int j=i;j;j--){
            if(a[i]==j) f[i][j]=max(f[i-1][j],f[i-1][j-1]+1);
            else f[i][j]=max(f[i-1][j],f[i-1][j-1]);
        }
    for(int i=1;i<=n;i++){
        ans=max(ans,f[n][i]);
    }
    cout<<ans;
    return 0;
}
View Code

 

posted @ 2018-09-17 21:42  滑稽的大白兔  阅读(117)  评论(0编辑  收藏  举报