zoukankan      html  css  js  c++  java
  • [Codeforces #192] Tutorial

    Link:

    Codeforces #192 传送门

    前两天由于食物中毒现在还要每天挂一天的水

    只好晚上回来随便找套题做做找找感觉了o(╯□╰)o

    A:

    看到直接大力模拟了

    但有一个更简便的方法,复杂度为$O(被禁止的格子数)$

    如果将每个黑格子上下左右四条线都染上色

    可以发现一个格子最终无法被“净化”当且仅当其被左右/上下来向都染过色,所以将最终无法净化的格子合并是一个矩形

    这样最终答案为:黑格子出现的行的个数*黑格子出现的列的个数

    此时复杂度就变成与黑格子个数相关了

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    int n,m,cnt,vis[20][20];char dat[20][20];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",dat[i]+1);
        for(int i=1;i<=n;i++)
        {
            bool f=0;
            for(int j=1;j<=m;j++)
                if(dat[i][j]=='S'){f=1;break;}
            if(f) continue;
            for(int j=1;j<=m;j++) vis[i][j]=1;
        }
        for(int i=1;i<=m;i++)
        {
            bool f=0;
            for(int j=1;j<=n;j++)
                if(dat[j][i]=='S'){f=1;break;}
            if(f) continue;
            for(int j=1;j<=n;j++) vis[j][i]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cnt+=vis[i][j];
        printf("%d",cnt);
        return 0;
    }
    Problem A

    B:

    发现菊花树满足任意两点之间距离不超过2

    因此只要找到中心点就好了

    又发现禁止的对数少于n/2,这样肯定有点没有禁止的点

    这样找到没有限制的点作为中心构造菊花树即可

    其实这是个结论:

    保证任意两点间距离不超过2,只有菊花树满足条件

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    int n,m,x,y,cnt[1005];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&x,&y),cnt[x]++,cnt[y]++;
        for(int i=1;i<=n;i++)
            if(!cnt[i])
            {
                printf("%d
    ",n-1);
                for(int j=1;j<=n;j++)
                    if(i!=j) printf("%d %d
    ",i,j);
                return 0;
            }
        return 0;
    }
    Problem B

    C:

    挺好想的,发现有解必为n个

    这样先排除无解情况再以行/列为基准顺次找到n个即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    int n,posr[105],posc[105];
    char dat[105][105];
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%s",dat[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(dat[i][j]=='.') posr[i]=j,posc[j]=i;
        bool f1=1,f2=1;
        for(int i=1;i<=n;i++)
        {
            if(!posr[i]) f1=0;
            if(!posc[i]) f2=0;
        }
        if(!f1&&!f2) return puts("-1"),0;
        if(f1)
            for(int i=1;i<=n;i++)
                printf("%d %d
    ",i,posr[i]);
        else
            for(int i=1;i<=n;i++)
                printf("%d %d
    ",posc[i],i);
        return 0;
    }
    Problem C

    D:

    可以将所有中途相遇都转化为终点相遇

    这样并不会使得是否相遇收到影响

    此时就能推出走最短路必定最优的结论了

    将终点设为BFS起点,将离终点比起点近的点都计入答案即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1005;
    P S,T;char dat[MAXN][MAXN];
    int n,m,res,dist[MAXN][MAXN],mx;
    int dx[]={0,0,1,-1};
    int dy[]={1,-1,0,0};
    
    int main()
    {
        memset(dist,-1,sizeof(dist));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",dat[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(dat[i][j]=='S') S=P(i,j);
                if(dat[i][j]=='E') T=P(i,j);
            }
        
        queue<P> q;q.push(T);
        dist[T.X][T.Y]=0;
        while(!q.empty())
        {
            P t=q.front();q.pop();
            int x=t.X,y=t.Y;
            for(int i=0;i<4;i++)
            {
                int fx=x+dx[i],fy=y+dy[i];
                if(fx<1||fx>n||fy<1||fy>m) continue;
                if(dist[fx][fy]!=-1||dat[fx][fy]=='T') continue;
                dist[fx][fy]=dist[x][y]+1;
                q.push(P(fx,fy));
            }
        }
        
        mx=dist[S.X][S.Y];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)//这里dist[i][j]!=-1不能漏 
                if(dat[i][j]>='0'&&dat[i][j]<='9'&&dist[i][j]!=-1&&dist[i][j]<=mx)
                    res+=dat[i][j]-'0';
        printf("%d",res);
        return 0;
    }
    Problem D

    E:

    考试时构造了很久确定解都觉得实现不了

    最后发现能随机艹过去……

    确定解:

    寻找确定解时,有一点是我也想到的:将最终解构造成一条链

    但还有一个重要性质:>=7时必定有解

    那么对于<=7的小数据阶乘暴力即可

    找到最大的连通块,将奇数项放前面,偶数项放后面

    同时将第一第二项交换位置(如ABCDEF->CAEBDF)

    这样就保证即使没有其它连通块,当前情况也能满足要求

    接下来将其它连通块不断间隔式插入即可

    在讨论里又看到了一个方法:

    将序列转换并使其保持如下性质:

    对于每个连通块,每一个点原来的相邻点都在其邻近的两格之内

    这样将i和i+3连边即可(待填坑……)

    随机算法:

    其实算一算随机一个序列正确的概率还是很高的

    (1-2/n)^n约等于0.135,反正随机100次应该就够了

    于是就愉快得不用构造确定解了……

    所以说,有时候还是要有点梦想

    算算概率说不定随机就能随便过了……

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    map<P,int> mp;
    int n,m,x,y,a[100005];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&x,&y),mp[P(x,y)]=1,mp[P(y,x)]=1;
        for(int i=1;i<=n;i++) a[i]=i;
        for(int i=1;i<=200;i++)
        {
            random_shuffle(a+1,a+n+1);
            bool f=1;a[n+1]=a[1];
            for(int j=1;j<=m;j++)
                if(mp[P(a[j],a[j+1])]){f=0;break;}
            if(!f) continue;
            for(int j=1;j<=m;j++)
                printf("%d %d
    ",a[j],a[j+1]);
            return 0;
        }
        puts("-1");
        return 0;
    }
    Problem E
  • 相关阅读:
    cocos2d-x学习记录5——CCTransition场景过渡
    cocos2d-x学习记录4——图形绘制
    cocos2d-x学习记录3——CCTouch触摸响应
    cocos2d-x学习记录2——CCAction动作
    cocos2d-x学习记录1——图片显示
    cocos2d-x环境搭建
    自定义CCNode
    cocos2d-x调度器原理
    cocos2d-x动作原理
    cocos2d-x触摸分发器原理
  • 原文地址:https://www.cnblogs.com/newera/p/9489364.html
Copyright © 2011-2022 走看看