zoukankan      html  css  js  c++  java
  • 2019-8-12 考试总结

    A. 引子 

    大模拟。

    先标记水箱的位置,然后顺着每条水管走,最后$dfs$就可以了。

    丑陋的代码:

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<vector>
    #define int long long
    #define Maxn 1050
    #define Reg register
    #define _max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    int n,m,cnt,tot,num[Maxn][Maxn];
    int Lx[Maxn*Maxn],Rx[Maxn*Maxn],Ly[Maxn*Maxn],Ry[Maxn*Maxn],stack[Maxn*Maxn];
    char s[Maxn][Maxn];
    vector<vector<int> > son(Maxn*Maxn);
    int find(int x,int y,int k)
    {
        if(x<1||x>n||y<1||y>m) return -1;
        if(num[x][y]) return num[x][y];
        else if(s[x][y]=='|')
        {
            s[x][y]='.';
            if(s[x+1][y]=='|'||s[x+1][y]=='+'||(num[x+1][y]&&num[x+1][y]!=k)) return find(x+1,y,k);
            else if(s[x-1][y]=='|'||s[x-1][y]=='+'||(num[x-1][y]&&num[x-1][y]!=k)) return find(x-1,y,k);
        }
        else if(s[x][y]=='-')
        {
            s[x][y]='.';
            if(s[x][y+1]=='-'||s[x][y+1]=='+'||(num[x][y+1]&&num[x][y+1]!=k)) return find(x,y+1,k);
            else if(s[x][y-1]=='-'||s[x][y-1]=='+'||(num[x][y-1]&&num[x][y-1]!=k)) return find(x,y-1,k);
        }
        else if(s[x][y]=='+')
        {
            s[x][y]='.';
            if(s[x+1][y]=='|'||s[x+1][y]=='+'||(num[x+1][y]&&num[x+1][y]!=k)) return find(x+1,y,k);
            else if(s[x-1][y]=='|'||s[x-1][y]=='+'||(num[x-1][y]&&num[x-1][y]!=k)) return find(x-1,y,k);
            else if(s[x][y+1]=='-'||s[x][y+1]=='+'||(num[x][y+1]&&num[x][y+1]!=k)) return find(x,y+1,k);
            else if(s[x][y-1]=='-'||s[x][y-1]=='+'||(num[x][y-1]&&num[x][y-1]!=k)) return find(x,y-1,k);
        }
        return -1;
    }
    void dfs(int x)
    {
        for(Reg int i=0;i<son[x].size();++i) dfs(son[x][i]);
        stack[++stack[0]]=x;
        return;
    }
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        for(Reg int i=0;i<=n+1;++i)
            for(Reg int j=0;j<=m+1;++j) s[i][j]='.';
        for(Reg int i=1;i<=n;++i) scanf("%s",s[i]+1);
        for(Reg int i=1;i<=n;++i)
        {
            for(Reg int j=1;j<=m;++j)
            {
                if(s[i][j]=='.') continue;
                else if(s[i][j]=='+')
                {
                    int lnow=j,rnow=j+1,unow=i,dnow=i+1,ok=1;
                    while(rnow<m&&s[i][rnow]=='-') ++rnow;
                    while(dnow<n&&s[dnow][j]=='|') ++dnow;
                    if(rnow>m||dnow>n) continue;
                    for(Reg int k=lnow+1;k<=rnow-1;++k) if(s[dnow][k]!='-') {ok=0; break;}
                    for(Reg int k=unow+1;k<=dnow-1;++k) if(s[k][rnow]!='|') {ok=0; break;}
                    if(!ok) continue;
                    if(s[i][rnow]=='+'&&s[dnow][j]=='+'&&s[dnow][rnow]=='+')
                    {
                        int po=0;
                        for(Reg int k=unow;k<=dnow;++k)
                        {
                            for(Reg int p=lnow;p<=rnow;++p)
                            {
                                if(s[k][p]>='0'&&s[k][p]<='9')
                                    po=po*10+s[k][p]-'0';
                                s[k][p]='.';
                            }
                        }
                        if(!po) continue;
                        for(Reg int k=unow;k<=dnow;++k)
                            for(Reg int p=lnow;p<=rnow;++p) num[k][p]=po;
                        cnt=_max(cnt,po);
                        Lx[po]=unow,Rx[po]=dnow,Ly[po]=lnow,Ry[po]=rnow;
                    }
                }
            }
        }
        for(Reg int i=1;i<=cnt;++i)
        {
            for(Reg int j=Rx[i];j>=Lx[i];--j)
            {
                if(s[j][Ly[i]-1]=='-')
                {
                    int p=find(j,Ly[i]-1,i);
                    if(p!=-1) son[i].push_back(p);
                }
                if(s[j][Ry[i]+1]=='-')
                {
                    int p=find(j,Ry[i]+1,i);
                    if(p!=-1) son[i].push_back(p);
                }
            }
        }
        dfs(1);
        for(Reg int i=1;i<=stack[0];++i) printf("%lld
    ",stack[i]);
        return 0;
    }
    View Code

    B. 可爱精灵宝贝

    乍一看这个题像一个很简单的$dp$,

    如果精灵不消失的话,那么就很简单了。

    但是精灵被抓住后会消失,这就有点难了。

    正解:

    用$dp[t][l][r][0/1]$表示状态,在第$t$秒左侧拓展到$l$,右侧拓展到$r$,现在在左端点$(0)/$在右端点$(1)$的最大收益。

    为什么可以这样。

    显然,要抓到一个精灵必须经过这个精灵到原点$k$之间的点,

    而如果这个点已经走过,那么再走肯定不会有收益。

    只要先把所有的精灵按照位置排序,然后枚举时间、左右端点就可以了。

    下面是转移:

    好吧很麻烦,看代码。

    #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=0,ans=0,tot=0,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;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

    C. 相互再归的鹅妈妈 

    总结:

    $T1$是个大模拟,

    数组开小$+$判水箱判错让我丢了$20$分,拿到$80$,

    $T1$大概码了不到一个小时,然后去看$T2$。

    $T2$看起来很简单,题目很好懂,

    一开始很自然地想到二维$dp$,但很快被$Hack$掉。

    观察题目性质,然后这个正解便很好想。

    $T2$码了一个多小时,然后又调了很长时间。

    最后剩下$T3$,好吧,容斥?组合数?一堆数学的东西。

    看起来很像按位转移的$dp$,好像没多少时间了。

    还是输出样例吧。。。

    总的来说心态很好(尤其是看到$T1$是个大模拟),

    $T2$能好好想了。

    时间分配,$T2$时间有点长,总的来说应该还行。

    好像给$T3$时间多了也拿不了多少分。。。

    不能想当然,很容易拿到$WA$。

    最后$80+100+10=190$

    没什么水平。。。

  • 相关阅读:
    android 的权限
    做android遇到有问题有感
    帮人写的 论文 C语言的 学生管理系统
    android 服务器的 mysql 查询悲剧
    android开发遇到的问题
    想和各位技术高人材交流技术特建了相关的QQ群
    Invalid token '44' in input string
    设置PLSQL Developer访问本机64位Oracle
    SQL Server 2005还原数据库时出现“不能选择文件或文件组XXX_log用于此操作……错误:3219……”的解决方法
    C#的JSON开发包 LitJSON
  • 原文地址:https://www.cnblogs.com/Milk-Feng/p/11340090.html
Copyright © 2011-2022 走看看