zoukankan      html  css  js  c++  java
  • 测试18:T2:可爱精灵宝贝

    我的考场剪枝搜索:500+ms

    一次扩展一段,只反向扩展,二维前后缀O(1)转移

    #include<bits/stdc++.h>
    #define F(i,a,b) for(rg int i=a;i<=b;++i)
    #define rg register
    #define il inline
    #define LL long long
    #define pf(a) printf("%d ",a)
    #define phn puts("")
    using namespace std;
    int read();
    /*
    删除调试语句。
    */
    //T pos dis
    int n,org,m,bigt;
    //int a[110],b[118],t[158];
    il int max(const int x ,const int y){return x>y?x:y;}
    int pre[4005][110],bac[4005][118];
    struct node{
        int a,b,t;
        friend bool operator < (node x,node y){
            return x.a<y.a;
        }
    }s[118];
    int ans;
    void dfs(int t,int pos,int las,int val){
        ans=max(ans,val);
    //    pf(t);phn;++tot;
        int fir,sum,tome;
        if(pos<=las){
            for(int i=las+1;i<=m;++i){
                fir=t-(s[pos].a-1)+2000;
                sum=pre[fir][i]-pre[fir][las];
                if(!sum)continue;
            /*    if(sum<0){
                    puts("88");while(1);
                }*/
                tome=t+s[i].a-s[pos].a;
                if(tome>bigt)break;
                dfs(tome,i,pos,val+sum);
            }
        }
        if(pos>=las){
            for(int i=las-1;i>=1;--i){
                fir=t-(n-s[pos].a)+2000;
                sum=bac[fir][i]-bac[fir][las];
                if(!sum)continue;
            /*    if(sum<0){
                    puts("88");while(1);
                }*/
                tome=t+s[pos].a-s[i].a;
                if(tome>bigt)break;
                dfs(tome,i,pos,val+sum);
            }
        }
    }
    int main(){
        n=read();org=read();m=read();
        s[m+1].a=org;s[m+1].b=0;s[m+1].t=0;
        F(i,1,m){
            s[i].a=read();s[i].b=read();s[i].t=read();bigt=max(bigt,s[i].t);
        }
        ++m;
        sort(s+1,s+m+1);
        int p=0;
        F(i,1,m){
            if(s[i].a==org){
                p=i;break;
            }
        }
        F(i,1,4001){
            F(j,1,m){
                pre[i][j]=pre[i][j-1]+(s[j].a-1+i>s[j].t+2000?0:s[j].b);
            }
            for(rg int j=m;j>=1;--j){
                bac[i][j]=bac[i][j+1]+(n-s[j].a+i>s[j].t+2000?0:s[j].b);
            }
        }    
        dfs(1,p,p,0);
        printf("%d
    ",ans);
    //    pf(tot);phn;
    }
    il int read(){
        int s=0;char ch;
        while(ch=getchar(),!isdigit(ch));
        for(;isdigit(ch);s=s*10+(ch^48),ch=getchar());
        return s;
    }
    /*
    g++ 2.cpp -g
    ./a.out
    
    
    
    10 5 4
    1 30 5
    3 5 7
    7 10 11
    9 100 23
    
    
    
    
    
    
    100 5 20
    1 30 5
    3 5 7
    7 10 12
    9 100 23
    10 30 5
    30 5 7
    70 10 12
    90 100 23
    11 30 5
    31 5 70
    71 10 102
    91 100 23
    12 30 5
    32 5 1500
    72 10 1200
    92 100 2000
    51 30 1500
    53 5 7
    57 10 12
    59 100 1500
    */
    View Code

    wxy 搜索:32ms

    一次只扩展一个。(clock会慢,无用)

    #include<bits/stdc++.h>
    #define ll long long
    #define cri const register int
    #define re register
    #define ll long long
    using namespace std;
    int ma=0,n,k,m,ans=0,sum=0,can[5000];
    struct node{
        int a,b,t;
        friend bool operator <(const node A,const node B){
            if(A.a==B.a) return A.b<B.b;
            return A.a<B.a;
        }
    }p[1100];
    void dfs(cri sta,int l,int r,cri tim,int sor,int lst){
        while(r<=m&&p[r].a==sta){
            lst-=p[r].b;
             if(p[r].t>=tim) sor+=p[r].b;
            r++;
        }
        while(l&&p[l].a==sta){
            lst-=p[l].b;
             if(p[l].t>=tim) sor+=p[l].b;
            l--;
        }
    //    if(clock()>995000){
    //        printf("%d
    ",ans);
    //        exit(0);
    //    }
    //    if(lst+sor<=ans||sor+can[ma]-can[tim]<=ans) return;
        while(l&&p[l].t<sta-p[l].a+tim) lst-=p[l].b,l--;
        while(r<=m&&p[r].t<p[r].a-sta+tim) lst-=p[r].b,r++;
    //    if(sor+lst<=ans) return;
        if(!l&&r>m) {
            ans=max(ans,sor);
            return;
        }
        if(r<=m) dfs(p[r].a,l,r,tim+p[r].a-sta,sor,lst);
        if(l) dfs (p[l].a,l,r,tim+sta-p[l].a,sor,lst);
    }
    int main(){
        scanf("%d%d%d",&n,&k,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].t);
            if(abs(p[i].a-k)+1>p[i].t) --i,--m;
            else sum+=p[i].b,can[p[i].t]+=p[i].b,ma=max(p[i].t,ma);
        }
        for(int i=1;i<=ma;i++) can[i]+=can[i-1];
        sort(p+1,p+m+1);
        int l=lower_bound(p+1,p+m+1,node{k,-1,0})-p;
        dfs(k,l-1,l,1,0,sum);
        printf("%d
    ",ans);
    }
    View Code

    milkfeng Dp(比大脸的1800+快多了):500+

    Tm^2。一次扩展一个

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define Maxn 2050
    #define Reg register
    #define INF 0x7fffff
    #define _max(x,y) ((x)>(y)?(x):(y))
    #define _abs(x) ((x)<0?(-1*(x)):(x))
    using namespace std;
    int n,k,m,mxx,ans,tot,mid,dp[Maxn][150][150][2];
    struct Node {int a,b,t;} Q[Maxn];
    bool comp(Node a,Node b) {return a.a<b.a;}
    int main()
    {
        scanf("%d%d%d",&n,&k,&m);
        Q[++tot].a=k,Q[tot].b=0,Q[tot].t=0;
        for(Reg int i=1,a,b,t;i<=m;++i)
        {
            scanf("%d%d%d",&a,&b,&t);
            if(a==k) Q[1].b+=b;
            else
            {
                Q[++tot].a=a,Q[tot].b=b,Q[tot].t=t;
                mxx=_max(mxx,Q[tot].t);
            }
        }
        sort(Q+1,Q+tot+1,comp);
        for(Reg int i=1;i<=tot;++i) if(Q[i].a==k) mid=i;
        for(Reg int i=1;i<=mxx;++i)
            for(Reg int j=mid;j>=1;--j)
                for(Reg int p=mid,sum;p<=tot;++p)
                    dp[i][j][p][0]=dp[i][j][p][1]=-INF;
        dp[1][mid][mid][0]=dp[1][mid][mid][1]=Q[mid].b;
        for(Reg int i=1;i<=mxx;++i)
        {
            for(Reg int j=mid;j>=1;--j)
            {
                for(Reg int p=mid,sum;p<=tot;++p)
                {
                    if(p+1<=tot&&i+Q[p+1].a-Q[j].a<=mxx)
                    {
                        sum=dp[i][j][p][0];
                        if(Q[p+1].t>=i+Q[p+1].a-Q[j].a) sum+=Q[p+1].b;
                        dp[i+Q[p+1].a-Q[j].a][j][p+1][1]=_max(dp[i+Q[p+1].a-Q[j].a][j][p+1][1],sum);
                    }
                    if(j-1>=1&&i+Q[j].a-Q[j-1].a<=mxx)
                    {
                        sum=dp[i][j][p][0];
                        if(Q[j-1].t>=i+Q[j].a-Q[j-1].a) sum+=Q[j-1].b;
                        dp[i+Q[j].a-Q[j-1].a][j-1][p][0]=_max(dp[i+Q[j].a-Q[j-1].a][j-1][p][0],sum);
                    }
                    if(j-1>=1&&i+Q[p].a-Q[j-1].a<=mxx)
                    {
                        sum=dp[i][j][p][1];
                        if(Q[j-1].t>=i+Q[p].a-Q[j-1].a) sum+=Q[j-1].b;
                        dp[i+Q[p].a-Q[j-1].a][j-1][p][0]=_max(dp[i+Q[p].a-Q[j-1].a][j-1][p][0],sum);
                    }
                    if(p+1<=tot&&i+Q[p+1].a-Q[p].a<=mxx)
                    {
                        sum=dp[i][j][p][1];
                        if(Q[p+1].t>=i+Q[p+1].a-Q[p].a) sum+=Q[p+1].b;
                        dp[i+Q[p+1].a-Q[p].a][j][p+1][1]=_max(dp[i+Q[p+1].a-Q[p].a][j][p+1][1],sum);
                    }
                    ans=_max(ans,_max(dp[i][j][p][0],dp[i][j][p][1]));
                }
            }
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    DP复杂度是稳定的。

    搜索这里虽然快,但是可以被卡,不稳定。(我赛后被北岸大神的点卡了)

    但是考场上想错了。想的Tm^3 DP。实际上Tm^2就可以。以为一次扩展一大截,实际上一次扩展一个就好。

    虽然有很多时间点是没用的,但冗余还是比搜索少,至少不会被卡。

    以后要尽量想这种复杂度确定的。

    (虽然很多人搜索A了)

    观察一开始想的,一次扩展一大节的,其实有很多是冗余的。例如:从i->i+1->i+2->i+3 和 i->i+3是等效的。

    似乎可以用搜索的思路每次只扩展相反的方向。感觉复杂度可能是一样的,在前后缀优化计算成O(1)后。

    只是常数可能会大。

    两种,一个是以反向返回为阶段划分,一个是以边界拓展一个为状态划分。

    只是没必要用第一种,复杂度应该是一样的,再用前缀和很麻烦,而且不能优化。

    第二种要打递推。递归式DP麻烦。而且想递归的话难想到这个转移。

    去想他运动的方式。

    Informatik verbindet dich und mich. 信息将你我连结。
  • 相关阅读:
    设计模式7—装饰者模式【结构型】
    设计模式6—命令模式【行为型】
    vue工程类型—vue 多模块、vue多项目集成工程
    设计模式5—迭代器模式【行为型】
    设计模式4—代理模式【结构型】
    设计模式3—策略模式【行为型】
    用户权限管理系统(后台权限管理)
    https原理 及 证书
    设计模式2—单例模式【创建型】
    设计模式1—发布订阅者模式【行为型】
  • 原文地址:https://www.cnblogs.com/seamtn/p/11339967.html
Copyright © 2011-2022 走看看