LCIS
单调优化思想
1 a[0]=b[0]=-9999; 2 FOR(i,1,n) 3 { 4 int val=0; 5 if(b[0]<a[i]) val=f[i-1][0]; 6 FOR(j,1,n) 7 { 8 if(a[i]==b[j]) f[i][j]=val+1; 9 else f[i][j]=f[i-1][j]; 10 if(b[j]<a[i]) val=max(val,f[i-1][j]); 11 } 12 } 13 FOR(i,1,n) ans=max(f[n][i],ans); 14 printf("%d",ans);
CH5102 Mobile Service http://contest-hunter.org:83/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%BE%8B%E9%A2%98/5102%20Mobile%20Service
三人的相对顺序不重要,考虑只记录两个不确定的位置
1 inline int rd() 2 { 3 rg int x(0),w(1); 4 rg char c(gc); 5 while(c<'0'||c>'9') {if(c=='-')w=-1;c=gc;} 6 while(c>='0'&&c<='9') x=x*10+c-48,c=gc; 7 return x*w; 8 } 9 10 11 void scan() 12 { 13 l=rd();n=rd(); 14 FOR(i,1,l) FOR(j,1,l) c[i][j]=rd(); 15 FOR(i,1,n) q[i]=rd(); 16 memset(f,8,sizeof(f)); 17 } 18 19 20 void dp() 21 { 22 q[0]=3;f[0][1][2]=0; 23 FOR(i,0,n-1) FOR(j,1,l) FOR(k,1,l) if(j!=k&&f[i][j][k]<=100000000) 24 { 25 if(j!=k &&q[i+1]!=j &&q[i+1]!=k) gmin(f[i+1][j][k],f[i][j][k]+c[q[i]][q[i+1]]); 26 if(q[i]!=k&&q[i+1]!=q[i]&&q[i+1]!=k) gmin(f[i+1][q[i]][k],f[i][j][k]+c[j][q[i+1]]); 27 if(q[i]!=j&&q[i+1]!=q[i]&&q[i+1]!=j)gmin(f[i+1][j][q[i]],f[i][j][k]+c[k][q[i+1]]); 28 } 29 } 30 31 void print() 32 { 33 FOR(i,1,l) FOR(j,1,l) ans=min(ans,f[n][i][j]); 34 printf("%d",ans); 35 }
P1006 传纸条https://www.luogu.org/problemnew/show/P1006
两条路同时走,将能用1、2、3维确定的第4维压掉
FOR(i,1,m) FOR(j,1,n) FOR(k,max(i+j-n,1),min(i+j-1,m)) { if(i==1&&j==1) f[i][j][k]=0; else if(i==k && !(i==m&&j==n)) f[i][j][k]=-9999999; else f[i][j][k]=a[i][j]+a[k][i+j-k]+ max(f[i-1][j][k-1],max(f[i][j-1][k-1],max(f[i-1][j][k],f[i][j-1][k]))); } cout<<f[m][n][m];
CH5104 I-country http://contest-hunter.org:83/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%BE%8B%E9%A2%98/5104%20I-country
凸连痛快问题,利用两个维度分别记录左右边界的单调性
1 const int N=16,K=230; 2 struct hhh{int ii,jj,ll,rr,xx,yy;}pre[N][K][N][N][2][2]; 3 int f[N][K][N][N][2][2],a[N][N]; 4 int n,m,k; 5 6 void scan() 7 { 8 n=rd();m=rd();k=rd(); 9 FOR(i,1,n) FOR(j,1,m) a[i][j]=rd(); 10 //memset(f,-8,sizeof(f)); 11 //FOR(i,1,n) f[i][0][0][0][1][0]; 12 //FOR(i,1,n){FOR(j,1,m)printf("%d",a[i][j]);printf(" ");} 13 } 14 15 void work() 16 { 17 FOR(i,1,n) FOR(j,1,k) FOR(l,1,m) for(rg int r=l;r<=m&&r-l<j;++r) 18 { 19 int t=0;FOR(ii,l,r) t+=a[i][ii]; 20 int cz=r-l+1; 21 //only widen 22 if(j==cz) 23 f[i][j][l][r][1][0]=t+f[i-1][0][0][0][1][0]; 24 else 25 { 26 //only widen 27 FOR(p,l,r) FOR(q,p,r) 28 if(f[i][j][l][r][1][0]<f[i-1][j-cz][p][q][1][0]) 29 f[i][j][l][r][1][0]=f[i-1][j-cz][p][q][1][0], 30 pre[i][j][l][r][1][0]={i-1,j-cz,p,q,1,0}; 31 //both right 32 FOR(p,1,l) FOR(q,l,r) FOR(x,0,1) 33 if(f[i][j][l][r][0][0]<f[i-1][j-cz][p][q][x][0]) 34 f[i][j][l][r][0][0]=f[i-1][j-cz][p][q][x][0], 35 pre[i][j][l][r][0][0]={i-1,j-cz,p,q,x,0}; 36 //both left 37 FOR(p,l,r) FOR(q,r,m) FOR(x,0,1) 38 if(f[i][j][l][r][1][1]<f[i-1][j-cz][p][q][1][x]) 39 f[i][j][l][r][1][1]=f[i-1][j-cz][p][q][1][x], 40 pre[i][j][l][r][1][1]={i-1,j-cz,p,q,1,x}; 41 //both unwiden 42 FOR(p,1,l) FOR(q,r,m) FOR(x,0,1) FOR(y,0,1) 43 if(f[i][j][l][r][0][1]<f[i-1][j-cz][p][q][x][y]) 44 f[i][j][l][r][0][1]=f[i-1][j-cz][p][q][x][y], 45 pre[i][j][l][r][0][1]={i-1,j-cz,p,q,x,y}; 46 FOR(x,0,1) FOR(y,0,1) f[i][j][l][r][x][y]+=t; 47 } 48 //printf("%d %d %d %d %d %d %d %d %d ",i,j,l,r,t, 49 //f[i][j][l][r][1][0],f[i][j][l][r][0][0],f[i][j][l][r][1][1],f[i][j][l][r][0][1]); 50 } 51 } 52 53 void dg(hhh ans) 54 { 55 if(!ans.jj) return; 56 dg(pre[ans.ii][ans.jj][ans.ll][ans.rr][ans.xx][ans.yy]); 57 FOR(i,ans.ll,ans.rr) printf("%d %d ",ans.ii,i); 58 } 59 60 void print() 61 { 62 int ans=-99999999;hhh as; 63 FOR(i,1,n) FOR(l,1,m) FOR(r,l,m) FOR(x,0,1) FOR(y,0,1) 64 if(ans<f[i][k][l][r][x][y]) 65 ans=f[i][k][l][r][x][y], 66 as={i,k,l,r,x,y}; 67 printf("Oil : %d ",ans); 68 dg(as); 69 }
CH5105 Cookies http://contest-hunter.org:83/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%BE%8B%E9%A2%98/5105%20Cookies
代价倒序排序,由于最后每人饼干数单调递减,每次转移
a.给每人发一个
b.给i前面的k个人分别发一个
const int N=32,M=5002; int g[N],f[N][M],a[N][M],b[N][M],c[N],ans[N],ran[N]; int n,m; bool cmp(int x,int y){return g[x]>g[y];} void scan() { n=rd();m=rd(); FOR(i,1,n) g[i]=rd(),ran[i]=i; sort(ran+1,ran+n+1,cmp); //FOR(i,1,n)printf("%d ",g[i]); FOR(i,1,n) c[i]=c[i-1]+g[ran[i]]; memset(f,8,sizeof(f)); f[0][0]=0; } void work() { FOR(i,1,n) FOR(j,i,m) { f[i][j]=f[i][j-i]; a[i][j]=i,b[i][j]=j-i; FOR(k,0,i-1) if(f[i][j]>f[k][j-(i-k)]+k*(c[i]-c[k])) f[i][j]=f[k][j-(i-k)]+k*(c[i]-c[k]), a[i][j]=k,b[i][j]=j-(i-k); } } void dg(int n,int m) { if(n==0) return; dg(a[n][m],b[n][m]); if(a[n][m]==n) FOR(i,1,n) ans[ran[i]]++; else FOR(i,a[n][m]+1,n) ans[ran[i]]=1; } void print() { printf("%d ",f[n][m]); dg(n,m); FOR(i,1,n) printf("%d ",ans[i]); }
P1541 乌龟棋 https://www.luogu.org/problemnew/show/P1541
1 FOR(i,0,c[1]) FOR(j,0,c[2]) FOR(k,0,c[3]) FOR(l,0,c[4]) 2 { 3 if(j) f[j][k][l]=max(f[j][k][l],f[j-1][k][l]); 4 if(k) f[j][k][l]=max(f[j][k][l],f[j][k-1][l]); 5 if(l) f[j][k][l]=max(f[j][k][l],f[j][k][l-1]); 6 f[j][k][l]+=a[i+(j<<1)+k+(k<<1)+(l<<2)]; 7 } 8 printf("%d",f[c[2]][c[3]][c[4]]);
P1854 花店橱窗布置 https://www.luogu.org/problemnew/show/P1854
1 void scan() 2 { 3 scanf("%d%d",&n,&m); 4 FOR(i,1,n) FOR(j,1,m) scanf("%d",&a[i][j]); 5 memset(f,-8,sizeof(f)); 6 FOR(i,0,n+1)f[i][0]=0; 7 } 8 9 void dp() 10 { 11 FOR(i,1,m) FOR(j,1,n) 12 { 13 //choose 14 f[i][j]=f[i-1][j],d1[i][j]=i-1,d2[i][j]=j; 15 //do not choose 16 if(f[i-1][j-1]+a[j][i]>f[i][j]) 17 f[i][j]=f[i-1][j-1]+a[j][i], 18 d1[i][j]=i-1,d2[i][j]=j-1,flag[i][j]=1; 19 } 20 } 21 22 void findpath(int i,int j) 23 { 24 if(i==0||j==0) return; 25 if(flag[i][j])FOR(ii,d1[i][j]+1,i) fl[ii]=j; 26 findpath(d1[i][j],d2[i][j]); 27 } 28 29 void print() 30 { 31 printf("%d ",f[m][n]); 32 findpath(m,n); 33 FOR(i,1,m) vase[fl[i]]=i; 34 FOR(i,1,n) printf("%d ",vase[i]); 35 }
poj1952 BUY LOW, BUY LOWER http://poj.org/problem?id=1952
1 void scan() 2 { 3 n=rd();a[0]=2e9;d[0]=1; 4 FOR(i,1,n) a[i]=rd(); 5 } 6 7 void dp() 8 { 9 FOR(i,1,n) 10 { 11 ll ans=-1; 12 For(j,i-1,0) if(a[j]>a[i]) gmax(ans,f[j]); 13 f[i]=ans+1; 14 For(j,i-1,0) 15 { 16 if(a[j]>a[i]&&f[j]==ans) d[i]+=d[j]; 17 else if(a[i]==a[j]&&f[i]==f[j]) break; 18 } 19 20 } 21 } 22 23 void print() 24 { 25 ll ans=0,num;FOR(i,1,n) 26 if(ans<f[i]){ans=f[i];num=d[i];} 27 else if(ans==f[i]) num+=d[i]; 28 printf("%lld %lld",ans,num); 29 }
luogu SP33 TRIP - Trip https://www.luogu.org/problemnew/show/SP33
1 const int N=82; 2 char s1[N],s2[N]; 3 int f[N][N],d1[N][26],d2[N][26]; 4 vector < string > s; 5 int n,m; 6 7 void create(int a1,int a2,int l,string ss) 8 { 9 if(l==0) {s.push_back(ss);return;} 10 FOR(i,0,25) if(f[d1[a1][i]][d2[a2][i]]==l) 11 create(d1[a1][i]-1,d2[a2][i]-1,l-1,(char)('a'+i)+ss); 12 } 13 14 void scan() 15 { 16 memset(s1,'