感觉都是基本的DP,除了charrec不好写罢了。
theme:求出差序列,然后求自身不同的最长公共子串。注意是不同的。
milk4:现ID-DFS枚举方案然后完全背包判定,我常数小直接过了,有TLE可以改记忆化搜索判定。
bigbrn:最大可行正方形,太基础了,连预处理都省了。。。。。
tour:两条线的DP,头脑发热要上SPFA的模板,让后仔细看了数据,三重循环结束。
charrec:很有价值,一般人看着就觉的太难了,然后仔细读完题想想就是DP,但确实不好写。
twofive:感觉最有价值的一道,首先它是一道构造/统计类的DP,然后又是五维DP,各种边界。显然有记忆化搜索比较赚。 

 最有价值的一题
最有价值的一题

 /**//*
/**//*
 USER:zyn19961
USER:zyn19961
 TASK:twofive
TASK:twofive
 LANG:C++
LANG:C++
 */
*/
 #include<string>
#include<string>
 #include<cstdio>
#include<cstdio>
 #include<cstring>
#include<cstring>
 #include<fstream>
#include<fstream>
 #include<iostream>
#include<iostream>
 #include<algorithm>
#include<algorithm> 
 using namespace std;
using namespace std;
 //
//
 #define MM(a,i) memset(a,i,sizeof(a))
#define MM(a,i) memset(a,i,sizeof(a))
 #define FOR(i,l,r) for (int i=(l);i<=(r);i++)
#define FOR(i,l,r) for (int i=(l);i<=(r);i++)
 #define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
#define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
 //
//
 #define MP make_pair
#define MP make_pair
 #define FT first
#define FT first
 #define SD second
#define SD second
 //
//
 typedef long long Int64;
    typedef long long Int64;
 const int INF=~0U>>2;
    const int INF=~0U>>2;
 const int maxn=10;
    const int maxn=10;
 //
//
 ifstream fin("twofive.in");
    ifstream fin("twofive.in");
 ofstream fout("twofive.out");
    ofstream fout("twofive.out");
 int F[maxn][maxn][maxn][maxn][maxn];
    int F[maxn][maxn][maxn][maxn][maxn];
 bool used[maxn*maxn];
    bool used[maxn*maxn];
 int mx[maxn],my[maxn];
    int mx[maxn],my[maxn];
 int count(int a,int b,int c,int d,int e,int now);
    int count(int a,int b,int c,int d,int e,int now);
 void work1();//n
    void work1();//n
 void work2();//w
    void work2();//w
 //
//

 int main()
    int main() {
{
 char c;fin>>c;
        char c;fin>>c;
 if(c=='N')work1();
        if(c=='N')work1();
 else work2();
        else work2();
 fin.close();
        fin.close();
 fout.close();
        fout.close();
 return 0;
        return 0; 
 }
        }

 int count(int a,int b,int c,int d,int e,int now)
    int count(int a,int b,int c,int d,int e,int now) {
{
 int &t=F[a][b][c][d][e];
        int &t=F[a][b][c][d][e];
 if(t)return t;
        if(t)return t;
 if(used[now])return t=count(a,b,c,d,e,now+1);//
        if(used[now])return t=count(a,b,c,d,e,now+1);//
 if(a<5&&mx[0]<now&&my[a]<now)t+=count(a+1,b,c,d,e,now+1);
        if(a<5&&mx[0]<now&&my[a]<now)t+=count(a+1,b,c,d,e,now+1);
 if(b<a&&mx[1]<now&&my[b]<now)t+=count(a,b+1,c,d,e,now+1);
        if(b<a&&mx[1]<now&&my[b]<now)t+=count(a,b+1,c,d,e,now+1);
 if(c<b&&mx[2]<now&&my[c]<now)t+=count(a,b,c+1,d,e,now+1);
        if(c<b&&mx[2]<now&&my[c]<now)t+=count(a,b,c+1,d,e,now+1);
 if(d<c&&mx[3]<now&&my[d]<now)t+=count(a,b,c,d+1,e,now+1);
        if(d<c&&mx[3]<now&&my[d]<now)t+=count(a,b,c,d+1,e,now+1);
 if(e<d&&mx[4]<now&&my[e]<now)t+=count(a,b,c,d,e+1,now+1);
        if(e<d&&mx[4]<now&&my[e]<now)t+=count(a,b,c,d,e+1,now+1);
 return t;
        return t;
 }
        }

 void work1()
    void work1() {
{
 int sum;fin>>sum;
        int sum;fin>>sum;
 int line[maxn];
        int line[maxn];
 string s;
        string s;
 MM(mx,0xff),MM(my,0xff),MM(used,false),MM(line,0);
        MM(mx,0xff),MM(my,0xff),MM(used,false),MM(line,0);

 FOR(i,0,24)
        FOR(i,0,24) {
{
 line[i/5]++;
            line[i/5]++;
 int j;
            int j;
 for(j=0;j<=24;j++)
            for(j=0;j<=24;j++)

 if(!used[j]&&mx[i/5]<j&&my[i%5]<j)
                if(!used[j]&&mx[i/5]<j&&my[i%5]<j) {
{
 used[j]=true;
                    used[j]=true;
 mx[i/5]=my[i%5]=j;
                    mx[i/5]=my[i%5]=j;
 MM(F,0);
                    MM(F,0);
 F[5][5][5][5][5]=1;
                    F[5][5][5][5][5]=1;
 int t=count(line[0],line[1],line[2],line[3],line[4],0);
                    int t=count(line[0],line[1],line[2],line[3],line[4],0);
 if(sum-t<=0)break;
                    if(sum-t<=0)break;
 else sum-=t;
                    else sum-=t;
 used[j]=false;
                    used[j]=false;
 }
                    }
 s+=char(j+'A');
            s+=char(j+'A');
 }
            }
 fout<<s<<"\n";
        fout<<s<<"\n";
 }
        }

 void work2()
    void work2() {
{
 string s;fin>>s;
        string s;fin>>s;
 int sum=0;
        int sum=0;
 int line[maxn];
        int line[maxn];
 MM(line,0),MM(mx,0),MM(my,0),MM(used,false);
        MM(line,0),MM(mx,0),MM(my,0),MM(used,false);

 FOR(i,0,24)
        FOR(i,0,24) {
{
 line[i/5]++;
            line[i/5]++;
 int j;
            int j;
 for(j=0;j<=s[i]-'A'-1;j++)
            for(j=0;j<=s[i]-'A'-1;j++)

 if(!used[j]&&mx[i/5]<j&&my[i%5]<j)
                if(!used[j]&&mx[i/5]<j&&my[i%5]<j) {
{
 mx[i/5]=my[i%5]=j;
                    mx[i/5]=my[i%5]=j;
 MM(F,0);
                    MM(F,0);
 F[5][5][5][5][5]=1;
                    F[5][5][5][5][5]=1;
 used[j]=true;
                    used[j]=true;
 sum+=count(line[0],line[1],line[2],line[3],line[4],0);
                    sum+=count(line[0],line[1],line[2],line[3],line[4],0);
 used[j]=false;
                    used[j]=false;
 }
                    }
 used[j]=true;
            used[j]=true;
 mx[i/5]=my[i%5]=j;
            mx[i/5]=my[i%5]=j;
 }
            }
 fout<<sum+1<<"\n";
        fout<<sum+1<<"\n";
 }
        }

接着看了一下Chapter 6的rectbarn
顾名思义,就是求最大子矩形,显然也是DP。
N久以前看过一篇集训队论文,然后就按照上面的一种方法A掉了这题。
(上面讲了两种方法,我显然写的是最水的N^2的算法)
恶搞了一下代码:

 见不得人的代码
见不得人的代码

 /**//*
/**//*
 USER:zyn19961
USER:zyn19961
 TASK:rectbarn
TASK:rectbarn
 LANG:C++
LANG:C++
 */
*/
 #include<cstdio>
#include<cstdio>
 #include<cstring>
#include<cstring>
 #include<fstream>
#include<fstream>
 #include<iostream>
#include<iostream>
 #include<algorithm>
#include<algorithm> 
 using namespace std;
using namespace std;
 //
//
 #define MM(a,i) memset((a),i,sizeof(a))
#define MM(a,i) memset((a),i,sizeof(a))
 #define FOR(i,l,r) for (int i=(l);i<=(r);i++)
#define FOR(i,l,r) for (int i=(l);i<=(r);i++)
 #define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
#define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
 #define NFOR(i,l,r) for (i=(l);i<=(r);i++)
#define NFOR(i,l,r) for (i=(l);i<=(r);i++)
 #define NDFOR(i,r,l) for (i=(r);i>=(l);i--)
#define NDFOR(i,r,l) for (i=(r);i>=(l);i--)
 #define PFOR(p,a,next) for(int p=a;p;p=next[p])
#define PFOR(p,a,next) for(int p=a;p;p=next[p])
 #define NPFOR(p,a,next) for(p=a;p;p=next[p])
#define NPFOR(p,a,next) for(p=a;p;p=next[p])
 //
//
 typedef long long int64;
 typedef long long int64;
 const int INF=~0U>>2;
 const int INF=~0U>>2;
 const int maxn=3001;
 const int maxn=3001; 
 //
//
 ifstream fin("rectbarn.in");
 ifstream fin("rectbarn.in");
 ofstream fout("rectbarn.out");
 ofstream fout("rectbarn.out");
 //
//
 bool xx[maxn][maxn];
 bool xx[maxn][maxn];
 int F[2][maxn],L[2][maxn],R[2][maxn],Left[maxn],Right[maxn];
 int F[2][maxn],L[2][maxn],R[2][maxn],Left[maxn],Right[maxn];

 int main()
 int main() {
{
 int r,c,p;
 int r,c,p;
 int x,y;
 int x,y;
 int ans=0,now=0,last=1;
 int ans=0,now=0,last=1;
 MM(xx,true);
 MM(xx,true);
 fin>>r>>c>>p;
 fin>>r>>c>>p;

 if(!p)
 if(!p) {fout<<r*c<<"\n";return 0;}
{fout<<r*c<<"\n";return 0;}
 FOR(i,1,p)fin>>x>>y,xx[y][x]=false;
 FOR(i,1,p)fin>>x>>y,xx[y][x]=false;

 FOR(i,1,c)
 FOR(i,1,c) {
{
 now^=1,last^=1;
 now^=1,last^=1;
 Left[0]=0,Right[r+1]=0;
 Left[0]=0,Right[r+1]=0;
 FOR(j,1,r)xx[i][j]?Left[j]=Left[j-1]+1:Left[j]=0;
 FOR(j,1,r)xx[i][j]?Left[j]=Left[j-1]+1:Left[j]=0;
 DFOR(j,r,1)xx[i][j]?Right[j]=Right[j+1]+1:Right[j]=0;
 DFOR(j,r,1)xx[i][j]?Right[j]=Right[j+1]+1:Right[j]=0;
 FOR(j,1,r)xx[i][j]? (F[now][j]=F[last][j]+1,
 FOR(j,1,r)xx[i][j]? (F[now][j]=F[last][j]+1,
 L[now][j]=min(L[last][j],Left[j]),
 L[now][j]=min(L[last][j],Left[j]),
 R[now][j]=min(R[last][j],Right[j]))
 R[now][j]=min(R[last][j],Right[j]))
 :(F[now][j]=0,L[now][j]=INF,R[now][j]=INF);
 :(F[now][j]=0,L[now][j]=INF,R[now][j]=INF);
 FOR(j,1,r)ans=max(ans,F[now][j]*(L[now][j]+R[now][j]-1));
 FOR(j,1,r)ans=max(ans,F[now][j]*(L[now][j]+R[now][j]-1));
 }
 }
 fout<<ans<<"\n";
 fout<<ans<<"\n";
 fin.close();
 fin.close();
 fout.close();
 fout.close();
 return 0;
 return 0; 
 }
 }
