先学习了一下状丫 找了几个比较简单的题
/*codevs 2596 售货员难题 状丫dp */ #include<cstdio> #include<cstring> #define maxn 50010 using namespace std; int n,g[20][20],f[maxn][20],ans; int min(int x,int y){ return x<y?x:y; } int main() { scanf("%d",&n);n--; memset(f,127/3,sizeof(f)); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) scanf("%d",&g[i][j]); ans=f[0][0];f[0][0]=0; for(int i=1;i<(1<<n);i++) for(int j=1;j<=n;j++)if(i&(1<<j-1)) for(int k=0;k<=n;k++) f[i][j]=min(f[i][j],f[i-(1<<j-1)][k]+g[k][j]); for(int i=1;i<=n;i++) ans=min(ans,f[(1<<n)-1][i]+g[i][0]); printf("%d ",ans); return 0; }
/*codevs 2800 送外卖 状丫dp 有个数据有点问题 2333*/ #include<cstdio> #include<cstring> #define maxn 40010 using namespace std; int n,g[16][16],f[maxn][16],ans; int min(int x,int y){ return x<y?x:y; } int main() { scanf("%d",&n); memset(f,127/3,sizeof(f)); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) scanf("%d",&g[i][j]); for(int k=0;k<=n;k++) for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) g[i][j]=min(g[i][j],g[i][k]+g[k][j]); ans=f[0][0];f[0][0]=0; for(int i=1;i<(1<<n);i++) for(int j=1;j<=n;j++)if(i&(1<<j-1)) for(int k=0;k<=n;k++) f[i][j]=min(f[i][j],f[i-(1<<j-1)][k]+g[k][j]); for(int i=1;i<=n;i++) ans=min(ans,f[(1<<n)-1][i]+g[i][0]); printf("%d ",ans); return 0; }
/*codevs 1358 状丫dp*/ #include<cstdio> #include<cstring> #define maxn 1500 using namespace std; int g[12][12],f[12][12][maxn],ans; int min(int x,int y){ return x<y?x:y; } int main() { for(int i=1;i<=10;i++) for(int j=1;j<=10;j++) scanf("%d",&g[i][j]); memset(f,127/3,sizeof(f)); f[1][1][1<<g[1][1]]=g[1][1]; int mxx=1<<10,SS; for(int i=1;i<=10;i++) for(int j=1;j<=10;j++) for(int S=0;S<mxx;S++){ SS=S|(1<<g[i+1][j]); f[i+1][j][SS]=min(f[i+1][j][SS],f[i][j][S]+g[i+1][j]); SS=S|(1<<g[i][j+1]); f[i][j+1][SS]=min(f[i][j+1][SS],f[i][j][S]+g[i][j+1]); } printf("%d ",f[10][10][mxx-1]); return 0; }
/*codevs 2594 状丫 dp */ #include<cstdio> #define inf 1e8 #define maxn 2500 using namespace std; int n,m,g[110][11],f[maxn]; int min(int x,int y){ return x<y?x:y; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&g[i][j]); for(int i=0;i<=(1<<n);i++) f[i]=inf; f[0]=0; for(int i=0;i<(1<<n);i++) for(int j=1;j<=m;j++){ int S=i; for(int k=1;k<=n;k++){ if(g[j][k]==0)continue; if(g[j][k]==1)S=S|(1<<k-1); if(g[j][k]==-1&&S&(1<<k-1)) S-=(1<<k-1); } f[S]=min(f[S],f[i]+1); } if(f[(1<<n)-1]==inf)printf("The patient will be dead. "); else printf("%d ",f[(1<<n)-1]); return 0; }
然后解决了历史遗留问题 现在看很简单吗似乎
/*codevs 1339 背包dp + 最丑的高精2333*/ #include<cstdio> #include<cstring> using namespace std; int n,m,t,W[25],cnt,f[25][25][510],dp[510],money[110],ans1[210],ans2[210]; char s[110]; int init(){ int x=0;char s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int max(int x,int y){ return x>y?x:y; } void mul1(int x){ ans1[0]=money[0]; for(int i=1;i<=ans1[0];i++) ans1[i]=money[i]*x; for(int i=1;i<=ans1[0];i++) if(ans1[i]>9){ ans1[i+1]+=ans1[i]/10;ans1[i]%=10; } if(ans1[ans1[0]+1])ans1[0]++; while(ans1[ans1[0]]>9){ ans1[ans1[0]+1]+=ans1[ans1[0]]/10; ans1[ans1[0]]%=10;ans1[0]++; } int k=1; for(int i=ans1[0];i>=1;i--) if(ans1[i]){ k=i;break; } ans1[0]=k; } void mul2(int x){ ans2[0]=money[0]; for(int i=1;i<=ans2[0];i++) ans2[i]=money[i]*x; for(int i=1;i<=ans2[0];i++) if(ans2[i]>9){ ans2[i+1]+=ans2[i]/10;ans2[i]%=10; } if(ans2[ans2[0]+1])ans2[0]++; while(ans2[ans2[0]]>9){ ans2[ans2[0]+1]+=ans2[ans2[0]]/10; ans2[ans2[0]]%=10;ans2[0]++; } int k=1; for(int i=ans2[0];i>=1;i--) if(ans2[i]){ k=i;break; } ans2[0]=k; } int main() { n=init();m=init();t=init();scanf("%s",s); int len=strlen(s); for(int i=len-1;i>=0;i--) if(s[i]>='0'&&s[i]<='9') money[++money[0]]=s[i]-'0'; for(int i=1;i<=n;i++){ scanf("%d",&W[i]); if(W[i]>t)cnt++; } for(int i=1;i<=m;i++) for(int l=1;l<=n;l++) for(int r=l;r<=n;r++){ for(int k=0;k<=t;k++)dp[k]=0; for(int k=l;k<=r;k++) for(int w=t;w>=W[k];w--) dp[w]=max(dp[w],dp[w-W[k]]+1); f[i][r][t]=max(f[i][r][t],f[i-1][l-1][t]+dp[t]); } mul1(f[m][n][t]);mul2(n-cnt-f[m][n][t]); for(int i=ans1[0];i>=1;i--)printf("%d",ans1[i]);printf(" "); for(int i=ans2[0];i>=1;i--)printf("%d",ans2[i]); return 0; }
最大正方形子矩阵 开始还wa了QAQ
/* codevs 1773 空间有点挤 猥琐的打short2333*/ #include<iostream> #include<cstdio> #define maxn 2510 using namespace std; short n,m,l[maxn][maxn],r[maxn][maxn],p[maxn][maxn],f[maxn][maxn],s[maxn][maxn],g[maxn][maxn],ans; short init(){ short x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int main() { n=init();m=init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ g[i][j]=init(); if(g[i][j])f[i][j]=s[i][j]=1; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(g[i-1][j]==0&&i>1) p[i][j]=p[i-1][j]+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(g[i][j-1]==0&&j>1) l[i][j]=l[i][j-1]+1; for(int i=1;i<=n;i++) for(int j=m;j>=1;j--) if(g[i][j+1]==0&&j<m) r[i][j]=r[i][j+1]+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(g[i][j]&&g[i-1][j-1])//min min min f[i][j]=min(f[i-1][j-1],min(l[i][j],p[i][j]))+1; ans=max(ans,f[i][j]); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(g[i][j]&&g[i-1][j+1]) s[i][j]=min(s[i-1][j+1],min(p[i][j],r[i][j]))+1; ans=max(ans,s[i][j]); } cout<<ans<<endl; return 0; }
多维LIS问题
/*codevs 1256 暴力n*n*m..... 20*/ #include<cstdio> #define maxn 110 using namespace std; int n,m,f[2][maxn][maxn],c[maxn],T,ans; short G[1010][maxn][maxn]; int init(){ int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int max(int x,int y){ return x>y?x:y; } int main() { freopen("mouse.in","r",stdin); freopen("mouse.out","w",stdout); n=init();m=init(); int x,y,t; for(int i=1;i<=m;i++){ t=init();x=init();y=init(); G[t][x][y]++;T=max(T,t); } for(int i=1;i<=T;i++){ for(int j=1;j<=n;j++) for(int k=1;k<=n;k++){ f[i&1][j][k]=f[i-1&1][j][k]; if(j>1)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j-1][k]+G[i][j][k]); if(k>1)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j][k-1]+G[i][j][k]); if(j<n)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j+1][k]+G[i][j][k]); if(k<n)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j][k+1]+G[i][j][k]); ans=max(ans,f[i&1][j][k]); } for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) f[i-1&1][j][k]=0; } printf("%d ",ans); return 0; } /* codevs 1256 这有点打脸啊...多维LIS问题居然没看出来 还是太弱...*/ #include<cstdio> #define maxn 10010 using namespace std; int n,m,f[maxn],x[maxn],y[maxn],t[maxn],ans; int init(){ int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int max(int x,int y){ return x>y?x:y; } int Abs(int x){ return x>0?x:-x; } int main() { freopen("mouse.in","r",stdin); freopen("mouse.out","w",stdout); n=init();m=init(); for(int i=1;i<=m;i++){ t[i]=init();x[i]=init();y[i]=init(); } for(int i=1;i<=m;i++){ for(int j=1;j<i;j++) if(Abs(x[i]-x[j])+Abs(y[i]-y[j])<=t[i]-t[j]) f[i]=max(f[i],f[j]+1); ans=max(ans,f[i]); } printf("%d ",ans+1); return 0; }
单调队列优化dp
/*codevs 3327 dp+单调队列优化 */ #include<iostream> #include<cstdio> #define maxn 100010 #define ll long long using namespace std; int n,k,q[maxn],head,tail; ll f[maxn],s[maxn],x,ans; ll init(){ ll x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='0')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } ll max(ll x,ll y){ return x>y?x:y; } void Insert(int x){ ll mx=f[x-1]-s[x]; while(head<=tail&&f[q[tail]-1]-s[q[tail]]<mx)tail--; q[++tail]=x; } int main() { n=init();k=init(); for(int i=1;i<=n;i++){ x=init();s[i]=s[i-1]+x; } Insert(1); for(int i=1;i<=n;i++){ if(i-q[head]>k)head++; f[i]=f[q[head]-1]-s[q[head]]+s[i]; Insert(i+1);ans=max(ans,f[i]); } cout<<ans<<endl; return 0; }
传说中的棋盘dp三水
/*codevs 2853 n*n*n*n 卡过*/ #include<cstdio> #define maxn 110 using namespace std; int n,g[maxn][maxn],f[2][maxn][maxn][maxn]; int Abs(int x){ return x>0?x:-x; } int max(int x,int y){ return x>y?x:y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&g[i][j]); for(int x1=1;x1<=n;x1++){ for(int y1=1;y1<=n;y1++) for(int x2=1;x2<=n;x2++) for(int y2=1;y2<=n;y2++){ f[x1&1][y1][x2][y2]=max(f [x1&1][y1][x2][y2],f[x1-1&1][y1][x2-1][y2]+Abs(g[x1][y1]-g[x2][y2])); f[x1&1][y1][x2][y2]=max(f [x1&1][y1][x2][y2],f[x1-1&1][y1][x2][y2-1]+Abs(g[x1][y1]-g[x2][y2])); f[x1&1][y1][x2][y2]=max(f [x1&1][y1][x2][y2],f[x1&1][y1-1][x2-1][y2]+Abs(g[x1][y1]-g[x2][y2])); f[x1&1][y1][x2][y2]=max(f [x1&1][y1][x2][y2],f[x1&1][y1-1][x2][y2-1]+Abs(g[x1][y1]-g[x2][y2])); } for(int y1=1;y1<=n;y1++) for(int x2=1;x2<=n;x2++) for(int y2=1;y2<=n;y2++) f[x1-1&1][y1][x2][y2]=0; } printf("%d ",f[n&1][n][n][n]); return 0; }
/*codevs 2853 优化 f[i][j][k] Ax=i By=j k步 那么左边可以表示了就 Orz */ #include<cstdio> #define maxn 210 using namespace std; int n,g[maxn][maxn],f[maxn][maxn][maxn*2]; int Abs(int x){ return x>0?x:-x; } int max(int x,int y){ return x>y?x:y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&g[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n*2-1;k++)if(k>j-1&&k>i-1){ f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j])); f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j])); f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j])); f[i][j][k]=max(f[i][j][k],f[i][j][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j])); } printf("%d ",f[n][n][2*n-1]); return 0; }
然后是线段覆盖类型 无聊打的nlogn优化
/*codevs 3095 */ #include<iostream> #include<cstdio> #include<algorithm> #define maxn 1000010 #define ll long long using namespace std; ll n,m,f[maxn],c[maxn],num,ans; struct node{ ll l,r; ll v; }p[maxn]; ll cmp(const node &x,const node &y){ return (x.r==y.r&&x.l<y.l)||x.r<y.r; } ll init(){ ll x=0;char s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int main() { m=init(); for(int i=1;i<=m;i++){ p[i].l=init();p[i].r=init(); p[i].v=init();c[i]=p[i].r; } sort(p+1,p+1+m,cmp);sort(c+1,c+1+m); for(int i=1;i<=m;i++){ ll pos=upper_bound(c+1,c+1+m,p[i].l)-c-1; f[i]=max(f[i-1],f[pos]+p[i].v); ans=max(ans,f[i]); } cout<<ans<<endl; return 0; }