• 2018湖南多校第二场20180407训练日志


    solve 4  (A  B  E  H)

    rank  15/32

    比赛链接:http://acm.csu.edu.cn:22080/cpcsys/contest/problemset?cid=1023

    A题Sim Card:(通过)

    签到题,且没什么可写的。

    B题Bank Card Verifier:(通过)

    签到题,跟着题目要求写就行了。

    C题Border Wall

    D题World Cup Draw

    E题Barareh on Fire:(通过)

    题意:火焰每k秒蔓延一次,能否从s点最快走到t点。

    思路:

    直接搜索,主要是每k秒更新一下新地图便可。

    可以直接预处理新地图,要省空间的话可以中途更新。

    其余的就是普通的bfs过程了。

    搜索题中比较考验码力的题,代码如下:

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <iostream>
    using namespace std;
    struct node
    {
        int x,y;
        int step;
        node(int x=0,int y=0,int step=0):x(x),y(y),step(step) {}
    };
    int mp[110][110][110],n,m,k;
    char ch[110];
    int bfs(int x,int y,int sx,int sy)
    {
        int vis[110][110]= {};
        queue<node> q;
        while(!q.empty()) q.pop();
        q.push(node(x,y,0));
        vis[x][y]=1;
        while(!q.empty())
        {
            node nod = q.front();
            if(nod.x==sx&&nod.y==sy) return nod.step;
            q.pop();
            if(nod.x>0&&!vis[nod.x-1][nod.y]&&mp[(nod.step+1)/k][nod.x-1][nod.y])
            {
                vis[nod.x-1][nod.y]=1;
                q.push(node(nod.x-1,nod.y,nod.step+1));
            }
            if(nod.x<n-1&&!vis[nod.x+1][nod.y]&&mp[(nod.step+1)/k][nod.x+1][nod.y])
            {
                vis[nod.x+1][nod.y]=1;
                q.push(node(nod.x+1,nod.y,nod.step+1));
            }
            if(nod.y>0&&!vis[nod.x][nod.y-1]&&mp[(nod.step+1)/k][nod.x][nod.y-1])
            {
                vis[nod.x][nod.y-1]=1;
                q.push(node(nod.x,nod.y-1,nod.step+1));
            }
            if(nod.y<m-1&&!vis[nod.x][nod.y+1]&&mp[(nod.step+1)/k][nod.x][nod.y+1])
            {
                vis[nod.x][nod.y+1]=1;
                q.push(node(nod.x,nod.y+1,nod.step+1));
            }
        }
        return -1;
    }
    int main()
    {
        int flag=1;
        while(scanf("%d %d %d",&n,&m,&k))
        {
            if(!n&&!m&&!k) break;
            int x,y,sx,sy;
            for(int i=0; i<n; i++)
            {
                scanf("%s",ch);
                for(int j=0; j<m; j++)
                {
    
                    if(ch[j]=='s')
                    {
                        mp[0][i][j]=1;
                        x=i;
                        y=j;
                    }
                    else if(ch[j]=='t')
                    {
                        mp[0][i][j]=1;
                        sx=i;
                        sy=j;
                    }
                    else if(ch[j]=='f')
                    {
                        mp[0][i][j]=0;
                    }
                    else if(ch[j]=='-')
                    {
                        mp[0][i][j]=1;
                    }
                }
            }
            for(int p=1; p<max(n,m); p++)
            {
                for(int i=0; i<n; i++)
                {
                    for(int j=0;j<m;j++)
                    {
                        mp[p][i][j]=1;
                        if(i>0&&j>0&&!mp[p-1][i-1][j-1]) mp[p][i][j]=0;
                        if(i>0&&!mp[p-1][i-1][j]) mp[p][i][j]=0;
                        if(j>0&&!mp[p-1][i][j-1]) mp[p][i][j]=0;
                        if(i>0&&j<m-1&&!mp[p-1][i-1][j+1]) mp[p][i][j]=0;
                        if(i<n-1&&j>0&&!mp[p-1][i+1][j-1]) mp[p][i][j]=0;
                        if(i<n-1&&!mp[p-1][i+1][j]) mp[p][i][j]=0;
                        if(j<m-1&&!mp[p-1][i][j+1]) mp[p][i][j]=0;
                        if(i<n-1&&j<m-1&&!mp[p-1][i+1][j+1]) mp[p][i][j]=0;
                    }
                }
            }
            int ans=bfs(x,y,sx,sy);
            if(ans==-1) printf("Impossible\n");
            else printf("%d\n",ans);
        }
        return 0;
    }
    
    /**********************************************************************
        Problem: 1263
        User: multi2018team024
        Language: C++
        Result: AC
        Time:164 ms
        Memory:7228 kb
    **********************************************************************/

    F题Homotopic Paths

    G题New Country Division

    H题Column Addition:(通过)

    题意:给长度为n的加法计算式a+b=c,问最少删除多少列使得式子正确。

    思路:

    <错误的贪心策略(虽然不知道哪里错了)>

    对于第pos位,如果(a[pos] + b[pos])%10==c[pos] 或者 (a[pos] + b[pos] +1)%10==c[pos] 

    pos位有可能留下,其余的一定要删掉(易证)。

    那么把必须删掉的提前处理完,从而达到剪枝的目的。

    <但是其实不需要贪心处理就可以ac这题>

    <一个正确的策略>

    由于数字最长只有1000位,我们不妨设dp[pos],表示第pos位合法时,能够得到的最长的合法序列有多长。

    (1)对于所有的pos:

    if((a[pos]+b[pos])%10==c[pos]) dp[pos]=1;

    (2)对于第pos位,能否跟第pos+x位连接起来的条件是:

    int jinwei=(dp[pos+x])&&(a[pos+x]+b[pos+x]>c[pos+x]);
    if((a[pos]+b[pos]+jinwei)%10==c[pos]) dp[pos]=max(dp[pos],dp[pos+x]+1);

    注意这里的变量 jinwei ,满足进位的条件当且仅当第pos+x位的a + b > c并且dp[pos+x]有值(如5+8=1这种式子是非法的,所以可以直接忽略掉,前面的贪心策略有处理掉这种非法式子)。

    (3)如果第pos位本位不进位,那么这一位可以作为新式子的最高位,所以答案可以这样更新:

    if((a[i]+b[i]<=c[i]))ans=min(ans,n-dp[i]);

    最后贴上dzc巨巨的ac代码:

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <iostream>
    #include <cstring>
    using namespace std;
    int n,ans=0;
    string s1,s2,s3;
    int a[1010],b[1010],c[1010],dp[1010];
    int main()
    {
        while(scanf("%d",&n)!=EOF&&n){
            ans=n;
            cin>>s1>>s2>>s3;
            for(int i=0;i<n;i++)
            {
                a[i]=s1[i]-'0';
                b[i]=s2[i]-'0';
                c[i]=s3[i]-'0';
            }
            memset(dp,0,sizeof(dp));
            for(int i=n-1;i>=0;i--)
            {
                if((a[i]+b[i])%10==c[i]) dp[i]=1;
                for(int j=i+1;j<n;j++)
                {
                    int jinwei=(dp[j])&&(a[j]+b[j]>c[j]);
                    if((a[i]+b[i]+jinwei)%10==c[i]) dp[i]=max(dp[i],dp[j]+1);
                }
            }
            for(int i=0;i<n;i++)
            {
                if((a[i]+b[i]<=c[i]))ans=min(ans,n-dp[i]);
            }
            printf("%d\n",ans);
        }
        return 0;
    }
    
    /**********************************************************************
        Problem: 1266
        User: multi2018team024
        Language: C++
        Result: AC
        Time:160 ms
        Memory:2040 kb
    **********************************************************************/

    I题Cafe Bazaar

    J题Getting Back Home

    K题Mars

  • 相关阅读:
    P2764 最小路径覆盖问题
    P1402 酒店之王 网络流
    P2597 [ZJOI2012]灾难 拓扑排序
    FJOI2017 矩阵填数
    2019.2.27模拟
    2019.2.26模拟
    SDOI2013 方程
    [AH2017/HNOI2017]抛硬币
    Lucas定理和扩展Lucas定理
    LuoguP4861 按钮
  • 原文地址:https://www.cnblogs.com/dowhile0/p/8734240.html
Copyright © 2020-2023  润新知