• 洛谷⑨月月赛Round2 官方比赛 OI


    自评:

    (完成时间3.5时)

    第一题 模拟 虽然A了,代码敲得有点慢

    第二题 最短路 第一次敲对了,又考虑数据范围和答案范围,改错了,100分改成42分。QAQ。

    第三题 乱搞 80分 还可以(因为没思路啊),不过也有A了的

    如果第二题不手贱的话,day1 280分,day2再随便写点,妥妥的一等。

    可惜没如果。(也还好不是联赛)。

    P3392 涂国旗

      • 10通过
      • 267提交
    • 题目提供者kkksc03
    • 标签
    • 难度普及-

      讨论  题解  

    最新讨论

    题目描述

    某国法律规定,只要一个由N*M个小方块组成的旗帜符合如下规则,就是合法的国旗。(毛熊:阿嚏——)

    • 从最上方若干行(>=1)的格子全部是白色的。

    • 接下来若干行(>=1)的格子全部是蓝色的

    • 剩下的行(>=1)全部是红色的

    现有一个棋盘状的破布,分成了N行M列的格子,每个格子是白色蓝色红色之一,小a希望把这个布改成该国国旗,方法是在一些格子上涂颜料,盖住之前的颜色。

    小a很懒,希望涂最少的格子,使这块破布成为一个合法的国旗。

    输入输出格式

    输入格式:

    第一行是两个整数,N,M

    接下来N行是一个矩阵,矩阵的每一个小方块是'W'(白),'B'(蓝),'R'(红)中的一个

    输出格式:

    一个整数,表示至少需要涂多少块。

    输入输出样例

    输入样例#1:
    4 5
    WRWRW
    BWRWB
    WRWRW
    RWBWR
    输出样例#1:
    11

    说明

    样例解释:

    目标状态是

    WWWWW
    BBBBB
    RRRRR
    RRRRR

    一共需要改11个格子

    对于100%的数据,N,M<=50

    100分代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=55;
    char mp[N][N],bf[N][N],w[N],b[N],r[N];
    int n,m,ans=0x7fffffff;
    inline int check(char *a,char *b){
        int res=0;
        for(int i=1;i<=m;i++) if(a[i]!=b[i]) res++;
        return res;
    }
    void dfs(){
        memcpy(bf,mp,sizeof mp);
        for(int i=1;i<=n-2;i++){
            int tans=0;
            for(int q=1;q<=i;q++){
                tans+=check(mp[q],w);
                memcpy(mp[q],w,sizeof w);
            } 
            for(int j=i+1;j<=n-1;j++){
                int t2=0,t3=0;
                for(int q=i+1;q<=j;q++){
                    t2+=check(mp[q],b);
                    memcpy(mp[q],b,sizeof b);
                } 
                for(int q=j+1;q<=n;q++){
                    t3+=check(mp[q],r);
                    memcpy(mp[q],r,sizeof r);
                }
                tans+=t2+t3;
                ans=min(ans,tans);
                for(int q=i+1;q<=n;q++) memcpy(mp[q],bf[q],sizeof bf[q]);
                tans-=t2+t3;
            }
            for(int q=1;q<=n;q++) memcpy(mp[q],bf[q],sizeof bf[q]);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
        for(int i=1;i<=m;i++) w[i]='W';
        for(int i=1;i<=m;i++) b[i]='B';
        for(int i=1;i<=m;i++) r[i]='R';
        dfs();
        printf("%d
    ",ans);
        return 0;
    }

    P3393 逃离僵尸岛

      • 1通过
      • 119提交
    • 题目提供者kkksc03
    • 标签
    • 难度尚无评定

      讨论  题解  

    最新讨论

    题目描述

    小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家。

    该国有N个城市,城市之间有道路相连。一共有M条双向道路。保证没有自环和重边。

    K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入。由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市。换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险。

    小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略。小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所以晚上要住旅店。安全的的城市旅馆比较便宜要P元,而被危险的城市,旅馆要进行安保措施,所以会变贵,为Q元。所有危险的城市的住宿价格一样,安全的城市也是。在1号城市和N城市,不需要住店。

    小a比较抠门,所以他希望知道从1号城市到N号城市所需要的最小花费。

    输入数据保证存在路径,可以成功逃离。输入数据保证他可以逃离成功。

    输入输出格式

    输入格式:

    第一行4个整数(N,M,K,S)

    第二行2个整数(P,Q)

    接下来K行,ci,表示僵尸侵占的城市

    接下来M行,ai,bi,表示一条无向边

    输出格式:

    一个整数表示最低花费

    输入输出样例

    输入样例#1:
    13 21 1 1
    1000 6000
    7
    1 2
    3 7
    2 4
    5 8
    8 9
    2 5
    3 4
    4 7
    9 10
    10 11
    5 9
    7 12
    3 6
    4 5
    1 3
    11 12
    6 7
    8 11
    6 13
    7 8
    12 13
    输出样例#1:
    11000

    说明

    对于20%数据,N<=50

    对于100%数据,2 ≦ N ≦ 100000, 1 ≦ M ≦ 200000, 0 ≦ K ≦ N - 2, 0 ≦ S ≦ 100000

    1 ≦ P < Q ≦ 100000

    100分代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    inline const int read(){
        register int x=0,f=1;
        register char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    #define ll long long
    #define xx first
    #define yy second
    #define pir pair<int,int>
    const int N=2e5+10;
    struct node{
        int v,next;
    }e[N<<1];
    int tot,head[N],js[N],pw[N];
    bool vis[N],JS[N];
    int n,m,s,k,P,Q;
    void add(int x,int y){
        e[++tot].v=y;
        e[tot].next=head[x];
        head[x]=tot;
    }
    void bfs(int S,int lim){
        int dis[N]={0};
        memset(vis,0,sizeof vis);
        queue<pir>q;
        q.push(make_pair(S,0));
        vis[S]=1;
        while(!q.empty()){
            pir h=q.front();q.pop();
            if(h.yy==lim) continue;
            for(int i=head[h.xx];i;i=e[i].next){
                if(!dis[e[i].v]){
                    dis[e[i].v]=dis[h.xx]+1;
                    if(!vis[e[i].v]){
                        vis[e[i].v]=1;
                        pw[e[i].v]=Q;
                        q.push(make_pair(e[i].v,dis[e[i].v]));
                    }
                }
            }
        }
    }
    void spfa(){
        ll dis[N];
        memset(dis,127,sizeof dis);
        memset(vis,0,sizeof vis);
        queue<int>q;
        q.push(1);
        dis[1]=0;
        vis[1]=1;
        while(!q.empty()){
            int h=q.front();q.pop();
            vis[h]=0;
            for(int i=head[h];i;i=e[i].next){
                int v=e[i].v;
                if(JS[v]) continue;
                if(dis[v]>dis[h]+(ll)pw[v]){
                    dis[v]=dis[h]+(ll)pw[v];
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v); 
                    }
                }
            }
        }
        printf("%lld
    ",dis[n]);
    }
    int main(){
        n=read(),m=read(),k=read(),s=read();
        P=read(),Q=read();
        for(int i=1;i<=k;i++) js[i]=read();
        for(int i=1,x,y;i<=m;i++) x=read(),y=read(),add(x,y),add(y,x);
        for(int i=1;i<=k;i++) bfs(js[i],s);
        for(int i=1;i<=n;i++) if(!pw[i]) pw[i]=P;pw[n]=0;
        for(int i=1;i<=k;i++) JS[js[i]]=1;
        spfa();
        return 0;
    }

    P3394 机器人的领域

      • 0通过
      • 97提交
    • 题目提供者kkksc03
    • 标签
    • 难度尚无评定

      讨论  题解  

    最新讨论

    题目描述

    一个机器人从xoy平面出发,按照给定的程序运行,程序中的一个字母ESWN分别表示机器人往东南西北走1米。我们会给出则一段有N个指令的程序。机器人将连续的执行这段程序K次。从原点开始,机器人每执行完一步,就会在地上做一个标记(原点也留了一个)。现在问,所有程序结束后,有多少个1*1的小方形,其四个顶点都被坐上了标记?

    输入输出格式

    输入格式:

    第一行两个整数,N,K

    第一行是长度为N的字符串,每个字符只会是一个字母ESWN分别表示机器人往东南西北走1米。

    输出格式:

    一个整数,表示符合要求的小方格数量

    输入输出样例

    输入样例#1:
    6 3
    SEENWS
    
    输出样例#1:
    6

    说明

    20% N<=50,K=1;

    另外20% k=1

    另外20% N<=50

    100% N<=100000,0<k<=10^9

    80分代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+100;  
    struct node{
        int x,y;
        bool operator < (const node a) const {
            if(x==a.x) return y<a.y;
            return x<a.x;
        }
        bool operator == (const node a) const{
            return x==a.x&&y==a.y;
        }
        bool operator != (const node a) const{
            return x!=a.x||y!=a.y;
        }
    }ans[N<<4];
    char s[N];
    int cnt,res,n,k;
    bool vis[3010][3010];
    node deal(int sx,int sy){
        ans[++cnt]=(node){sx,sy};
        int len=strlen(s);
        for(int i=0;i<len;i++){
            if(s[i]=='N') ans[++cnt]=(node){++sx,sy};
            else if(s[i]=='S') ans[++cnt]=(node){--sx,sy};
            else if(s[i]=='W') ans[++cnt]=(node){sx,--sy};
            else if(s[i]=='E') ans[++cnt]=(node){sx,++sy};
        }
        node t;
        t.x=sx;
        t.y=sy;
        return t;
    }
    int ef(node x){
        int l=1,r=cnt;
        while(l<r){
            int mid=l+r>>1;
            if(x<ans[mid]||ans[mid]==x) r=mid;
            else l=mid+1;
        }
        return l;
    }
    int solve(){
        sort(ans+1,ans+cnt+1);
        cnt=unique(ans+1,ans+cnt+1)-(ans+1);
        for(int i=1;i<=cnt;i++){
            if(!vis[ans[i].x+1500][ans[i].y+1500]){
                node la=(node){ans[i].x,ans[i].y+1};
                node ra=(node){ans[i].x-1,ans[i].y};
                node aa=(node){ans[i].x-1,ans[i].y+1};
                int lp=ef(la);
                if(ans[lp]!=la) continue;
                int rp=ef(ra);
                if(ans[rp]!=ra) continue;
                int pp=ef(aa);
                if(ans[pp]!=aa) continue;
                res++;
                vis[ans[i].x+1500][ans[i].y+1500]=1;
            }
        }
    }
    int main(){
        scanf("%d%d%s",&n,&k,s);
        node t=deal(0,0);
        solve();
        int r1=res;
        if(k==1){printf("%d",res);return 0;}
        else{
            deal(t.x,t.y);
            solve();
            int r2=res-r1;
            printf("%lld
    ",(ll)r1+(ll)r2*(ll)(k-1));
            //cout<<(ll)r1+(ll)r2*(ll)(k-1);
        }
        return 0;
    }

     改后的AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    using namespace std;
    struct node{
        int x,y;
        bool operator < (const node& a)const{
            return x<a.x||(x==a.x&&y<a.y);
        }
    };
    set<node>S;
    long long n,k,ans,lr,r;
    char s[100010];
    int main(){
        scanf("%d%d%s",&n,&k,s);
        node now;
        now.x=0;now.y=0;
        S.insert(now);
        for(int i=1;i<=k;i++){
            r=0;
            for(int j=0;j<n;j++){
                if(s[j]=='E')now.y++;
                if(s[j]=='W')now.y--;
                if(s[j]=='S')now.x--;
                if(s[j]=='N')now.x++;
                if(S.count(now)==0){
                    node a,b,c,d,e,f,g,h;
                    a.x=now.x-1;a.y=now.y-1;b.x=now.x-1;b.y=now.y;
                    c.x=now.x-1;c.y=now.y+1;d.x=now.x;d.y=now.y-1;
                    e.x=now.x;e.y=now.y+1;f.x=now.x+1;f.y=now.y-1;
                    g.x=now.x+1;g.y=now.y;h.x=now.x+1;h.y=now.y+1;
                    if(S.count(a)==1&&S.count(b)==1&&S.count(d)==1)r++;
                    if(S.count(b)==1&&S.count(c)==1&&S.count(e)==1)r++;
                    if(S.count(d)==1&&S.count(f)==1&&S.count(g)==1)r++;
                    if(S.count(e)==1&&S.count(g)==1&&S.count(h)==1)r++;
                    S.insert(now);
                }
            }    
            if(r==lr){
                ans+=(k-i+1)*r;
                break;
            }
            ans+=r;lr=r;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    5-python基础—获取某个目录下的文件列表(适用于任何系统)
    Automated, Self-Service Provisioning of VMs Using HyperForm (Part 1) (使用HyperForm自动配置虚拟机(第1部分)
    CloudStack Support in Apache libcloud(Apache libcloud中对CloudStack支持)
    Deploying MicroProfile-Based Java Apps to Bluemix(将基于MicroProfile的Java应用程序部署到Bluemix)
    Adding Persistent Storage to Red Hat CDK Kit 3.0 (在Red Hat CDK Kit 3.0添加永久性存储)
    Carve Your Laptop Into VMs Using Vagrant(使用Vagran把您笔记本电脑刻录成虚拟机)
    使用Python生成一张用于登陆验证的字符图片
    Jupyter notebook的安装方法
    Ubuntu16.04使用Anaconda5搭建TensorFlow使用环境 图文详细教程
    不同时区的换算
  • 原文地址:https://www.cnblogs.com/shenben/p/5904208.html
Copyright © 2020-2023  润新知