线性DP

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 }
View Code

 

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("\n");}
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\n",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\n",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\n",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\n",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\n",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,'\0',sizeof(s1));
17     memset(s2,'\0',sizeof(s2));
18     memset(f,0,sizeof(f));
19     memset(d1,0,sizeof(d1));
20     memset(d2,0,sizeof(d2));
21     s.clear();
22     scanf("%s",s1+1);scanf("%s",s2+1);
23     n=strlen(s1+1),m=strlen(s2+1);
24 }
25 
26 void dp()
27 {
28     FOR(i,1,n) FOR(j,1,m)
29     {
30         if(s1[i]==s2[j]) gmax(f[i][j],f[i-1][j-1]+1);
31         gmax3(f[i][j],f[i-1][j],f[i][j-1]);
32     }
33     FOR(i,1,n) FOR(j,0,25)
34         if(s1[i]-'a'==j) d1[i][j]=i;
35         else d1[i][j]=d1[i-1][j];
36     FOR(i,1,m) FOR(j,0,25)
37         if(s2[i]-'a'==j) d2[i][j]=i;
38         else d2[i][j]=d2[i-1][j];
39     create(n,m,f[n][m],"");
40 }
41 
42 void print()
43 {
44     sort(s.begin() , s.end());
45     FOR(i,0,s.size()-1) cout<<s[i]<<endl;
46     printf("\n");
47 }

 

posted @ 2019-04-05 21:27  universeplayer  阅读(169)  评论(0编辑  收藏  举报