zoukankan      html  css  js  c++  java
  • Codeforces Round #648 (Div. 2) A、B、C、D、E、F

    题目
    A题意:给出一个n*m的棋盘,初始每个格子为0或1.现在Ashish(先手)和Vivek玩一个游戏,都采取最优策略,判断谁赢
    规则:双方轮流在方格为0且该方格的行列上都没1,才可放1.最终不能放1的一方失败。
    解法:分别统计行和列上没有1的数量,因为每放一个1都会消耗1行和1个列。所以只需判断满足条件的行列的最小值的奇偶性就可得到答案,奇数先手赢。

    const int maxn = 59;
    int a[maxn][maxn] ;
    bool visx[maxn] , visy[maxn] ;
    
    void solve(){
        ME(visx , false);
        ME(visy , false);
        int n , m ;
        cin >> n >> m ;
        rep(i , 1 , n){
            rep(j , 1 , m){
                cin >> a[i][j];
                if(a[i][j]){
                    visx[i] = 1;//标记被1占用行
                    visy[j] = 1;
                }
            }
        }
        int x = 0 , y = 0 ;
        rep(i , 1 , n){
            if(!visx[i]) x++;//计数满足条件行
        }
        rep(i , 1 , m){
            if(!visy[i]) y++;
        }
        if(min(x,y)%2){//判断最小值奇偶
            cout << "Ashish" << endl;
        }else{
            cout << "Vivek" << endl;
        }
    }
    
    signed main()
    {
        int _ ;cin>>_;while(_--)
            solve();
    }
    
    

    B题意:n个元素,每个元素有(a_i)价值,和类型(b_i)(0或1).不同类型之间的元素可以交换。
    问是否可以使元素以价值不减的顺序排列。
    解法:如果给出序列已经有序,则满足条件。如果两种类型的元素都有,也满足条件。
    分析后一种情况:对于任意一对需要交换的元素a和b,并假设其类型相同,选一个与其类型不同的元素c。
    通过c,可以达到a与b交换的目的,所以可满足条件。

    const int maxn = 2e5+9;
    int a[maxn] , b[maxn];
    void solve(){
        int n ;
        cin >> n ;
        rep(i , 1 , n){
            cin >> a[i];
        }
        int flag = 1 ;
        rep(i , 1,  n-1){
            if(a[i] > a[i+1]){
                flag = 0 ;
                break;
            }
        }
        int x = 0 ,  y = 0;
        rep(i , 1,  n){
            cin >> b[i];
            if(!b[i])x++;
            else y++;
        }
        if((x&&y) || flag){
            cout << "YES" << endl;
        }else{
            cout << "NO" << endl;
        }
    }
     
    signed main()
    {
        //ios::sync_with_stdio(false);
        //cin.tie(0); cout.tie(0);
        int _ ;cin>>_;while(_--)
            solve();
    }
    

    C题意:给出两组排列a和b,可对排列进行左右移动(首尾相连),比如n位置元素右移变到1位置。
    问:最多a排列与b排列,下标相同且值相同的最大个数。
    解法:固定a数组,且记录a数组中各个元素的位置。遍历b数组,记录元素(b_i)在b数组与(b_i)在a数组之间需要移动次数。可以知道相同移动次数最多即是答案。

    int a[maxn] , b[maxn];
    int pos[maxn];
    int cnt[maxn];//记录需i次的数量
    void solve(){
        int n ;
        cin >> n ;
        rep(i , 1 , n){
            cin >> a[i] ;
            pos[a[i]] = i ;
        }
        rep(i , 1 , n){
            cin >> b[i];
        }
        rep(i , 1 , n){
            int c = i - pos[b[i]];
            if(c<0) c+=n;
            cnt[c]++;
        }
        int ans = 0 ;
        rep(i , 0 , n-1){
            ans = max(cnt[i] , ans);
        }
        cout << ans << endl;
    }
    

    D题意:n*m大小迷宫,.代表路,G代表好人,B代表坏人,#代表墙。
    可以将路(.)变成墙(#),问是否可以使所有好人可以到达(n,m),所有坏人不能到达(n,m)处。
    解法:将所有坏人相邻的路变墙,然后判断是否所有的好人都可达(n,m)。
    有种情况需要注意:当坏人与好人相邻时,则一定是不可行的,因为此时他们能不能到达(n,m)是一致的。
    优化:正向对每一个好人dfs判断能否到达(n,m)时间上是不可行的,所以需要反向dfs出口能达到所有的点,然后判断是否好人所在的点能否达到。

    #include<bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include <vector>
    typedef long long ll ;
    #define int ll
    #define mod 1000000007
    #define gcd __gcd
    #define rep(i , j , n) for(int i = j ; i <= n ; i++)
    #define red(i , n , j)  for(int i = n ; i >= j ; i--)
    #define ME(x , y) memset(x , y , sizeof(x))
    //ll lcm(ll a , ll b){return a*b/gcd(a,b);}
    ll quickpow(ll a , ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;b>>=1,a=a*a%mod;}return ans;}
    //int euler1(int x){int ans=x;for(int i=2;i*i<=x;i++)if(x%i==0){ans-=ans/i;while(x%i==0)x/=i;}if(x>1)ans-=ans/x;return ans;}
    //const int N = 1e7+9; int vis[n],prime[n],phi[N];int euler2(int n){ME(vis,true);int len=1;rep(i,2,n){if(vis[i]){prime[len++]=i,phi[i]=i-1;}for(int j=1;j<len&&prime[j]*i<=n;j++){vis[i*prime[j]]=0;if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}else{phi[i*prime[j]]=phi[i]*phi[prime[j]];}}}return len}
    #define SC scanf
    #define INF  0x3f3f3f3f
    #define PI acos(-1)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(v) v.begin(),v.end()
    #define size(v) (int)(v.size())
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    using namespace std;
    const int N = 1e6+7;
    const int maxn = 59;
    char s[maxn][maxn];
    int n , m ;
    bool vis[maxn][maxn];
    int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    int vi[maxn][maxn];
    void dfs(int x , int y){
        vis[x][y] = 1 ;
        for(int i = 0 ; i < 4 ; i++){
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if(s[xx][yy] == '#' || xx <= 0 || xx > n || yy <= 0 || yy > m || vis[xx][yy]) continue ;
            dfs(xx , yy);
        }
    }
    
    void solve(){
        int flag = 0 ;
        ME(vi , false);
        ME(vis , false);
        cin >> n >> m;
        rep(i , 1 , n){
            rep(j , 1 , m){
                cin >> s[i][j];
                if(s[i][j] == 'G'){
                    vi[i][j] = 1 ;
                }
            }
        }
        rep(i , 1 , n){
            rep(j , 1 , m){
                if(s[i][j] == 'B'){
                    rep(k , 0 , 3){
                        int xx = i+dir[k][0];
                        int yy = j+dir[k][1];
                        if(xx <= 0 || xx > n || yy <= 0 || yy > m) continue;
                        if(s[xx][yy] == '.')s[xx][yy] = '#';//给坏人周围变墙
                        if(s[xx][yy] == 'G'){//如果坏人周围有好人,则不符合条件
                            cout << "NO" << endl;
                            return;
                        }
                    }
                }
            }
        }
        if(s[n][m] == '.')//从出口dfs
            dfs(n , m);
        rep(i , 1 , n){
            rep(j , 1 , m){
                if(vi[i][j]){//好人所在的点
                    if(!vis[i][j]){//能否从出口可达
                        cout << "NO" << endl;
                        return ;
                    }
                }
            }
        }
        cout << "YES" << endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        int _ ;cin>>_;while(_--)
            solve();
    }
    
    

    E题意:给出一组n个序列,子序列长度k的值为子序列满足条件的二进制位之和,要至少有max(k-2,1)个元素具有该二进制位算满足条件。
    问子序列最大值位多少。
    解法:如果当k大于3时新增的数的二进制位一定在前三个数中出现的位数的集合中,所以最大有效个数为三个.(巢鸽原理)
    所以只需暴力枚举任意三个数

    const int maxn = 5e2+9;
    int a[maxn];
    
    void solve(){
        int n ;
        cin >> n ;
        rep(i , 1 , n){
            cin >> a[i];
        }
        if(n == 1){
            cout << a[1] << endl;
            return ;
        }
        if(n == 2){
            cout << (a[1]|a[2]) << endl;
            return;
        }
        int ans = 0 ;
        rep(i ,1 , n){
            rep(j , i+1 , n){
                rep(k , j+1 , n){
                    ans = max(ans , a[i]|a[j]|a[k]);
                }
            }
        }
        cout << ans << endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        //int _ ;cin>>_;while(_--)
            solve();
    }
    

    F题意:给出n个数ai , n个数bi,问通过操作a数组是否可以变为b。
    操作:对于长度k(1<=k<=[(frac{n}{2})]),前缀k个元素与后缀k个元素进行交换,比如a:[1,4,2,3] 操作k=2,a:[2,3,1,4];
    解法:1、可以知道当n为奇数时,a中心数与b中心数一定要相等。
    2、因为交换都是中心交换,所以a的所有((a_i,a_{n-i+1})) 与b所有((b_i,b_{n-i+1})),应该完全相同。

    int a[maxn] , b[maxn];
    
    void solve(){
        int n ;
        cin >> n ;
        rep(i , 1 , n){
            cin >> a[i];
        }
        rep(i , 1 , n){
            cin >> b[i];
        }
        if(n % 2 == 1){
            if(a[n/2+1] != b[n/2+1]){
                cout << "NO" << endl;
                return ;
            }
        }
        map<pii , int>m;
        pii p ;
        rep(i , 1 , n){
            if(a[i] > a[n-i+1]) swap(a[i] , a[n-i+1]);//记录a的配对
            p = {a[i] , a[n-i+1]};
            m[p]++;
        }
        rep(i , 1 , n){
            if(b[i] > b[n-i+1]) swap(b[i] , b[n-i+1]);
            p = {b[i] , b[n-i+1]};
            m[p]--;
            if(m[p] < 0){//如果b的配对与a的配对不一致
                cout << "NO" << endl;
                return ;
            }
        }
        cout << "YES" << endl;
    }
    
  • 相关阅读:
    Eclipse 远程调试
    大数据处理方法bloom filter
    sicily 1259 Sum of Consecutive Primes
    sicily 1240. Faulty Odometer
    sicily 1152 简单马周游 深度优先搜索及回溯算法
    sicily 1050 深度优先搜索解题
    sicily 1024 邻接矩阵与深度优先搜索解题
    sicily 1156 二叉树的遍历 前序遍历,递归,集合操作
    sicily 1443 队列基本操作
    sicily 1006 team rankings 枚举解题
  • 原文地址:https://www.cnblogs.com/nonames/p/13069805.html
Copyright © 2011-2022 走看看