【[kuangbin带你飞]专题十二 基础DP1】题解 除了 K S

A
题意 求最大M子段和
其实就是 dp[i][j] 代表以i结尾(i必须取) 已经有j个子段的最大值
那么dp[i][j] 只能通过 dp[i-1][j] 和 dp[i-1][j-1] 过来
dp[i]代表到i位置分的段数
滚动数组优化一维后发现其实和BZOJ 1270有异曲同工之妙
记录一个最大值 然后最大值作为上一个循环的最大值传过来进行直接传递

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e6+5;
int n,m,arr[N];
//int f[N][N];
int dp[N],maxn[N];
int main(){
    while(scanf("%d%d",&m,&n)==2)
    {
        for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
        memset(dp,0,sizeof(dp));
        memset(maxn,0,sizeof(maxn));
        int nowans = 0;
        for(int i = 1;i<=m;++i)
        {
            nowans = -1e9;
            for(int j = i ;j<=n;++j)
            {
                dp[j] = max(dp[j-1],maxn[j-1]) + arr[j];
                maxn[j-1] = nowans;
                nowans = max(dp[j],nowans);
            }
        }
        printf("%d\n",nowans);
    }
    return 0;
}


B
求至少出现n/2的次数
不知道为啥在dp专题里 我直接sort过的

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1000025;
int arr[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n;
    while(scanf("%d",&n)==1)
    {
        for(int i = 1;i<=n;++i)
            scanf("%d",&arr[i]);
        sort(arr+1,arr+1+n);
        printf("%d\n",arr[n/2+1]);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

C
猴子摆塔
做法就是把每一个东西都衍生出5个新东西
然后按照 长从大到小 宽从大到小 类似Lis 的求法去求出答案即可

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 200;
int dp[MAX_N];
struct node
{
    int x,y,z;
    bool operator<(const node other) const
    {
        if(x==other.x)
        {
            if(y==other.y)
            {
                return z > other.z;
            }
            return y >other.y;
        }
        return x > other.x;
    }
}arr[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,ans,Case = 0;
    while(scanf("%d",&n)==1)
    {
        ans = 0;
        if(!n) break;
        for(int i = 1;i<=n;++i)
        {
            scanf("%d%d%d",&arr[i].x,&arr[i].y,&arr[i].z);
            arr[n*1+i].x = arr[i].x,arr[n*1+i].y = arr[i].z,arr[n*1+i].z = arr[i].y;
            arr[n*2+i].x = arr[i].y,arr[n*2+i].y = arr[i].z,arr[n*2+i].z = arr[i].x;
            arr[n*3+i].x = arr[i].y,arr[n*3+i].y = arr[i].x,arr[n*3+i].z = arr[i].z;
            arr[n*4+i].x = arr[i].z,arr[n*4+i].y = arr[i].x,arr[n*4+i].z = arr[i].y;
            arr[n*5+i].x = arr[i].z,arr[n*5+i].y = arr[i].y,arr[n*5+i].z = arr[i].x;
        }
        sort(arr+1,arr+1+6*n);
        for(int i = 1;i<=6*n;++i) dp[i] = arr[i].z;
        for(int i = 1;i<=6*n;++i)
        {
            for(int j = 1;j<i;++j)
            {
                if(arr[i].x<arr[j].x&&arr[i].y<arr[j].y)
                {
                    dp[i] = max(dp[i],dp[j]+arr[i].z);
                }
            }
        }
        for(int i = 1;i<=6*n;++i)
            ans = max(ans,dp[i]);
        printf("Case %d: maximum height = %d\n",++Case,ans);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

D
做作业 发现作业只有15个 很容易想到状态压缩
那么我们枚举几个作业的时候 就要找这么多作业包含的那一个作业
然后枚举去掉他和加上他的情况 来进行dp
主要是位运算操作都在代码里面
然后用pre 数组输出答案

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 200;
char str[16][MAX_N];
struct node
{
    int l,r;
}arr[16];
int pre[65545],dp[65545],tm[65545];
void write(int x)
{
    if(x==0) return;
    write(x^(1<<pre[x]));
    printf("%s\n",str[pre[x]]);

}
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 0;i<n;++i) scanf("%s%d%d",str[i],&arr[i].l,&arr[i].r);
        memset(dp,0x3f,sizeof(dp));
        dp[0] = 0;
        for(int i = 1;i<(1<<n);++i)
        {
            for(int j = n-1;j>=0;--j)
            {
                int tt = 1<<j;
                if(!(i&tt)) continue;
                tt = i^tt;
                int tmp = tm[tt] + arr[j].r - arr[j].l;
                tmp = tmp<0?0:tmp;
                if(dp[i]>dp[tt]+tmp)
                {
                    dp[i] = dp[tt]+tmp;
                    tm[i] = tm[tt] + arr[j].r;
                    pre[i] = j;
                }
            }
        }
        printf("%d\n",dp[(1<<n)-1]);
        write((1<<n)-1);
        memset(pre,0,sizeof(pre));
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

E
类似Lis 只不过状态转移方程要统计的是每个点的权值和

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int arr[MAX_N];
ll dp[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n;
    while(scanf("%d",&n)==1)
    {
        ll ans = 0;
        if(!n) break;
        for(int i = 1;i<=n;++i)
            scanf("%d",&arr[i]),dp[i] = arr[i];
        for(int i = 1;i<=n;++i)
            for(int j = 1;j<i;++j)
            {
                if(arr[i]>arr[j])
                {
                    dp[i] = max(dp[i],dp[j]+arr[i]);
                }
            }
        for(int i = 1;i<=n;++i)
            ans = max(ans,dp[i]);
        printf("%lld\n",ans);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

F
题意 给你开始重量和结束重量 问你装最少的钱使得重量加上开始重量等于结束重量
完全背包水题

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 505;
int val[MAX_N],v[MAX_N];
long long dp[10025];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int t,E,F,n;scanf("%d",&t);
    while(t--)
    {
    scanf("%d%d",&E,&F);
    scanf("%d",&n);for(int i = 1;i<=n;++i)  scanf("%d%d",&val[i],&v[i]);
    memset(dp,0x7f7f7f7f,sizeof(dp));
    ll tmp = dp[F];
    dp[0] = 0;F -= E;
    for(int i = 1;i<=n;++i)
    {
        for(int j = v[i];j<=F;++j)
        {
            dp[j] = min(dp[j],dp[j-v[i]]+val[i]);
        }
    }
    if(dp[F]==tmp) printf("This is impossible.\n");
    else printf("The minimum amount of money in the piggy-bank is %lld.\n",dp[F]);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

G
中文题面
dp[i][j]代表第 i 秒 第 j 坐标的地方能接的方案数
因为 0 到 11 所以我把坐标都加了1

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
int dp[100025][15],arr[100025][15];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,x,tm,ans,maxx;
    while(scanf("%d",&n)==1)
    {
        ans = 0;
        if(!n) break;
        memset(arr,0,sizeof(arr));
        memset(dp,0x80,sizeof(dp));
        dp[0][6] = 0;
        for(int i = 1;i<=n;++i)
        {
            scanf("%d%d",&x,&tm),x++;
            arr[tm][x]++;
        }
        for(int i = 1;i<100000;i++)
        {
            for(int j = 1;j<=11;j++)
            {
                if(j==1) dp[i][j] = max(dp[i-1][j],dp[i-1][j+1]) + arr[i][j];
                else if(j==11) dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + arr[i][j];
                else dp[i][j] = max(dp[i-1][j],max(dp[i-1][j-1],dp[i-1][j+1])) + arr[i][j];
                ans = max(dp[i][j],ans);
            }
        }
        printf("%d\n",ans);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

H
买票 容易想到dp[i]代表第i个人已经买完票的花费
那么我们顺推过去 dp[i] = max(dp[i-1]+arr[i],dp[i-2]+b[i])

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 2025;
int arr[MAX_N],dp[MAX_N],b[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int t;scanf("%d",&t);
    while(t--)
    {
        int n;scanf("%d",&n);
        for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
        for(int i = 2;i<=n;++i) scanf("%d",&b[i]);b[1] = 0x3f3f3f3f;
        memset(dp,0x3f,sizeof(dp));
        dp[0] = 0;
        for(int i = 1;i<=n;++i)
        {
            if(i==1) dp[i] = dp[i-1]+arr[i];
            else dp[i] = min(dp[i-1]+arr[i],dp[i-2]+b[i]);
        }
        int tmp__ = dp[n]%60,tmp_ = dp[n]/60%60,tmp = dp[n]/3600;
        printf("%02d:%02d:%02d ",tmp+8,tmp_,tmp__);
        if(tmp+8>=12) printf("pm\n");
        else printf("am\n");
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

I
求的是最长上升子序列长度 一开始忘记从2开始WA了一发
这是nlogn的实现方法 原理就是我们的这个Lis 如果相同位置 我要值最小的
这样后面才有可能塞更多东西

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 30025;
int arr[MAX_N],ans[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n;
    while(scanf("%d",&n)==1)
    {
        int len = 1;
        for(int i = 1;i<=n;++i)
            scanf("%d",&arr[i]);
        ans[len] = arr[1];
        for(int i = 2;i<=n;++i)
            if(arr[i]>ans[len]) ans[++len] = arr[i];
            else *(lower_bound(ans+1,ans+1+len,arr[i])) = arr[i];
        printf("%d\n",len);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

J
题意 求第一个序列递增 第二个序列递降的最长长度以及序列
我们只要按照第一个个序列递增 第二个序列递减排序 用求Lis的方法求最长长度
并且用vector记录取的序列

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int dp[MAX_N];
vector<int > vt[MAX_N];
struct node
{
    int l,r,id;
    bool operator<(const node other) const
    {
        if(l==other.l) return r > other.r;
        return l < other.l;
    }
}arr[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int ans = 1,xb = 1,n = 1;
    while(scanf("%d%d",&arr[n].l,&arr[n].r)==2)
    {
        arr[n].id = n;
        n++;
    }
    n--;
    sort(arr+1,arr+1+n);
    for(int i = 1;i<=n;++i) dp[i] = 1,vt[i].push_back(arr[i].id);
    for(int i = 1;i<=n;++i)
    {
        for(int j = 1;j<i;++j)
        {
            if(arr[i].l>arr[j].l&&arr[i].r<arr[j].r)
            {
                if(dp[i]<dp[j]+1)
                {
                    dp[i] = dp[j]+1;
                    vector<int> vt_;
                    swap(vt[i],vt_);
                    int sz = vt[j].size();
                    for(int k = 0;k<sz;++k) vt[i].push_back(vt[j][k]);
                    vt[i].push_back(arr[i].id);
                    if(ans<dp[i])
                    {
                        ans = dp[i];
                        xb = i;
                    }
                }
            }
        }
    }
    printf("%d\n",ans);
    for(int i = 0;i<vt[xb].size();i++)
        printf("%d\n",vt[xb][i]);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

L
LCS水题
dp[i][j] 代表 第一个串的 i 长度 和第二个串的 j 长度的最长公共子序列长度

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 10025;
char str[MAX_N],str_[MAX_N];
int dp[MAX_N][MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    while(scanf("%s%s",str+1,str_+1)==2)
    {
        int len = strlen(str+1),len_ = strlen(str_+1);
        for(int i = 1;i<=len;++i)
            for(int j = 1;j<=len_;++j)
                dp[i][j] = 0;
        for(int i = 1;i<=len;++i)
            for(int j = 1;j<=len_;++j)
                if(str[i]==str_[j]) dp[i][j] = dp[i-1][j-1] + 1;
                else dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
        printf("%d\n",dp[len][len_]);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

M
好久以前自己写出来的 不优雅 现在也忘记dp意义了没看这题

/*
POJ 1661
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
//#define dbg(x) cout<<#x<<" = "<< (x)<< endl
using namespace std;
const int MAX_N = 20024;
struct node
{
    int l;
    int r;
    int h;
    bool operator < (const node other) const
    {
        if(h==other.h&&l==other.l)
            return r<other.r;
        if(h==other.h)
            return l<other.l;
        return h<other.h;
    }
} arr[MAX_N];
long long dp[MAX_N][2];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0x3f,sizeof(dp));
        int n,x,y,H;
        scanf("%d%d%d%d",&n,&x,&y,&H);
        for(int i = 1; i<=n; ++i)
            scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].h);
        sort(arr+1,arr+1+n);
        arr[0].l = -20022;
        arr[0].r = 20022;
        arr[0].h = 0;
        arr[n+1].l = x;
        arr[n+1].r = x;
        arr[n+1].h = y;
        dp[n+1][1] = 0;
        dp[n+1][0] = 0;
        for(int i = n; i>=0; i--)
        {
            if(i==0)
            {
                for(int j = 1; j<=n+1; j++)
                {
                    int flag = 0,flag_l = 0,flag_r=0;
                    if(arr[j].h-arr[i].h>H)
                        break;
                    if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l&&arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].l<arr[j].l&&arr[k].r>arr[j].l)
                                {
                                    flag_l = 1;
                                    break;
                                }
                            }
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].l<arr[j].r&&arr[k].r>arr[j].r)
                                {
                                    flag_r = 1;
                                    break;
                                }
                            }
                        }
                        if(flag_l&&flag_r)
                            continue;
                        else if(flag_l)
                        {
                            dp[0][0] = min(dp[0][0],dp[j][1]+arr[j].h);
                        }
                        else if(flag_r)
                        {
                            dp[0][0] = min(dp[0][0],dp[j][0]+arr[j].h);
                        }
                        else
                            dp[0][0] = min(dp[0][0],min(dp[j][0],dp[j][1])+arr[j].h);
                    }
                    else if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].r>arr[j].l&&arr[k].l<arr[j].l)
                                {
                                    flag = 1;
                                    break;
                                }
                            }
                        }
                        if(flag)
                            continue;
                        dp[0][0] = min(dp[0][0],dp[j][0]+arr[j].h);
                    }
                    else if(arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].r>arr[j].r&&arr[k].l<arr[j].r)
                                {
                                    flag = 1;
                                    break;
                                }
                            }
                        }
                        if(flag)
                            continue;
                        dp[0][0] = min(dp[0][0],dp[j][1]+arr[j].h);
                    }
                    else
                        continue;
                }
            }
            else
            {
                for(int j = i+1; j<=n+1; j++)
                {
                    int flag_l = 0,flag_r=0,flag = 0;
                    if(arr[j].h-arr[i].h>H)
                        break;
                    if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l&&arr[j].r<=arr[i].r)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].l<arr[j].l&&arr[k].r>arr[j].l)
                                {
                                    flag_l = 1;
                                    break;
                                }
                            }
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].l<arr[j].r&&arr[k].r>arr[j].r)
                                {
                                    flag_r = 1;
                                    break;
                                }
                            }
                        }
                        if(flag_l&&flag_r)
                            continue;
                        else if(flag_l)
                        {
                            dp[i][0] = min(dp[i][0],dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h);
                            dp[i][1] = min(dp[i][1],dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h);
                        }
                        else if(flag_r)
                        {
                            dp[i][0] = min(dp[i][0],dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h);
                            dp[i][1] = min(dp[i][1],dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h);
                        }
                        else
                        {
                            dp[i][0] = min(dp[i][0],min(dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h,dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h));
                            dp[i][1] = min(dp[i][1],min(dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h,dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h));
                        }
                    }
                    else if(arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].r>arr[j].r&&arr[k].l<arr[j].r)
                                {
                                    flag = 1;
                                    break;
                                }
                            }
                        }
                        if(flag)
                            continue;
                        dp[i][0] = min(dp[i][0],dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h);
                        dp[i][1] = min(dp[i][1],dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h);
                    }
                    else if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l)
                    {
                        if(j!=i+1)
                        {
                            for(int k = i+1; k<j; k++)
                            {
                                if(arr[k].r>arr[j].l&&arr[k].l<arr[j].l)
                                {
                                    flag = 1;
                                    break;
                                }
                            }
                        }
                        if(flag)
                            continue;
                        dp[i][0] = min(dp[i][0],dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h);
                        dp[i][1] = min(dp[i][1],dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h);
                    }
                    else
                        continue;
                }
            }
        }
        printf("%lld\n",min(min(dp[1][0],dp[1][1])+arr[1].h,dp[0][0]));
    }
    return 0;
}


N
最水的LIS

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int arr[MAX_N],ans[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int len = 1,n;scanf("%d",&n);
    for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
    ans[len] =  arr[1];
    for(int i = 2;i<=n;++i)
        if(arr[i]>ans[len]) ans[++len] = arr[i];
        else *(lower_bound(ans+1,ans+1+len,arr[i])) = arr[i];
    printf("%d\n",len);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

O
敦敦敦讲过的区间dp
我们定义dp[l][r]就是 l 到 r 按照此规则形成的答案
那么我们知道 dp[l][r] 只能从 dp[l+1][r] 和 dp[l][r-1] 形成
那么我们根据这个性质去转移dp就可以了
然后对于每个串 你是知道他加串的那个顺序的

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 2025;
int arr[MAX_N],dp[MAX_N][MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,ans = 0;scanf("%d",&n);
    for(int i = 1;i<=n;++i) scanf("%d",&arr[i]),dp[i][i] = arr[i];
    arr[0] = 0,arr[n+1] =0;
    for(int i = n;i>=1;--i)
    {
        for(int j = i;j<=n;++j)
        {
            dp[i][j] = max(dp[i+1][j]+(n+i-j)*arr[i],dp[i][j-1]+(n+i-j)*arr[j]);
        }
    }
    printf("%d\n",dp[1][n]);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

P
搜索的时候采用记忆化 然后直接返回答案即可

/*
hdoj 1078
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
using namespace std;
const int MAX_N = 124;
int k,n;
long long dp[MAX_N][MAX_N],arr[MAX_N][MAX_N];
int dir[4][2] = {1,0,-1,0,0,-1,0,1};
long long dfs(int x,int y){
   long long ans = 0;
   if(!dp[x][y]){
    for(int i = 1;i<=k;i++){
        for(int j = 0;j<4;j++){
            int xx = x + dir[j][0]*i;
            int yy = y + dir[j][1]*i;
            if(xx<1||xx>n||yy<1||yy>n) continue;
            if(arr[xx][yy]>arr[x][y]) ans=max(ans,dfs(xx,yy));
        }
    }
     dp[x][y] = ans;
   }
   return dp[x][y]+arr[x][y];
}
int main(){
   while(scanf("%d%d",&n,&k)){
    memset(dp,0,sizeof(dp));
    if(n==-1&&k==-1) break;
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=n;j++)
         scanf("%lld",&arr[i][j]);
    printf("%lld\n",dfs(1,1));
   }
   return 0;
}

Q题的哈希是跟学长学的 十分的妙

/*
hdoj 2859
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1e3+5;
ull hash_1[maxn][maxn],hash_2[maxn][maxn],xp[maxn];
char str[maxn][maxn];
void init()
{
    xp[0]=1;
    for(int i=1;i<maxn;i++)
        xp[i]=xp[i-1]*13331;//这里13331玄学数字,大概可以随意换
    return ;
}
void make_hash(int n)//处理出str的hash值
{
    for(int i=0;i<n;i++)
    {
        hash_1[i][n]=0;
        for(int j=n-1;j>=0;j--)
        {
            hash_1[i][j]=hash_1[i][j+1]*13331+(str[i][j]-'A')+1;
        }
    }
    for(int i=0;i<n;i++)
    {
        hash_2[i][n]=0;
        for(int j=n-1;j>=0;j--)
        {
            hash_2[i][j]=hash_2[i][j+1]*13331+str[j][i]-'A'+1;
        }
    }
    return ;
}
ull Get_hash1(int x,int i,int L)//得到起点为i,长度为L的子串的hash值
{
    return hash_1[x][i]-hash_1[x][i+L]*xp[L];
}
ull Get_hash2(int x,int i,int L)//得到起点为i,长度为L的子串的hash值
{
    return hash_2[x][i]-hash_2[x][i+L]*xp[L];
}
int dp[maxn][maxn];
int main()
{
    int n;
    init();
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        for(int i=0;i<n;i++) scanf("%s",str[i]);
        for(int i=0;i<n;i++) strrev(str[i]);
        make_hash(n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                dp[i][j]=1;
        int ans=1;
        for(int i=1;i<n;i++)
        {
            for(int j=1;j<n;j++)
            {
                 int tmp=dp[i-1][j-1];
                 for(int len=tmp;len>=0;len--)
                 {
                    ull tmp1=Get_hash1(i,j-len,len+1);
                    ull tmp2=Get_hash2(j,i-len,len+1);
                    if(tmp1==tmp2)
                    {
                        dp[i][j]=len+1;
                        break;
                    }
                 }
                 ans=max(ans,dp[i][j]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

R把奶牛挤奶时间排个序 先按照挤奶时间从开始时间递增排序
按照Lis 的思想去更新答案即可
dp[i]代表到这个奶牛结尾产生的最大值

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
struct node
{
    int l,r,v;
    bool operator<(const node other) const
    {
        if(l==other.l) return r>other.r;
        return l < other.l;
    }
}arr[MAX_N];
int dp[MAX_N];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,m,t,ans = 0;scanf("%d%d%d",&n,&m,&t);
    for(int i = 1;i<=m;++i) scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].v),arr[i].r+=t;
    sort(arr+1,arr+1+m);
    for(int i = 1;i<=m;++i) dp[i] = arr[i].v;
    for(int i = 1;i<=m;++i)
    {
        for(int j = 1;j<i;++j)
        {
            if(arr[i].l>=arr[j].r)
            {
                dp[i] = max(dp[i],dp[j] + arr[i].v);
            }
        }
    }
    for(int i = 1;i<=m;++i)
        ans = max(ans,dp[i]);
    printf("%d\n",ans);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/heucodesong/article/details/89355018