普通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; }
扫雷
两列扫雷方格,给第二列数字,问第一列有几种可能
本来是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; }
数列_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; }