Codeforces Round #648 (Div. 2)A-E(伪博弈+思维+暴力+BFS+思维/暴力/位运算)

A:http://codeforces.com/contest/1365/problem/A

题意:

n*m的01矩阵,操作是把0变为1,条件是这个0所在的行列均无1。给出先手,求胜者。

解析:

改变一个0,那么它所在的行列均不能再使用。

设不含1的列有x,不含1的行有y,那么min(x,y)即为可操作数。

看下奇偶就行了。

#include <cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
const int maxn=60;
int mp[maxn][maxn];
int v[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                cin>>mp[i][j];
        }
        int c1=0,c2=0;
        for(int i=1;i<=n;i++)
        {
            int sum=0;
            for(int j=1;j<=m;j++)
                sum+=mp[i][j];
            if(sum==0)
                c1++;
        }
        for(int j=1;j<=m;j++)
        {
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                sum+=mp[i][j];
            }
            if(sum==0)
                c2++;
        }
        int md=min(c1,c2);
        if(md%2==0)
            cout<<"Vivek"<<endl;
        else
            cout<<"Ashish"<<endl;
    }
}

B:http://codeforces.com/contest/1365/problem/B

题意:

a[],b[](0/1)

a[i]和a[j]交换条件是b[i]和b[j]不同,操作任意次

问能否把a[]变成非递减序列

解析:

刚开始上去就写了个冒泡,其实不对,因为题目是可以进行任意的交换的。

可以发现,只要b[]存在一对不同,那么就可以把a[]进行任意的摆放,一定可以把它变成非递减序列。

当然先判断a[]本身是否为非递减序列

#include <cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
const int maxn=600;
int a[maxn],b[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        int ok = 0,ok2=0;
        for(int i=1;i<n;i++)
        {
            if(a[i]>a[i+1])
            {
                ok2=1;break;
            }
        }
        if(!ok2)
        {
            cout<<"Yes"<<endl;continue;
        }
        for(int i=1;i<n;i++)
        {
            if(b[i]!=b[i+1])
            {
                ok=1;cout<<"Yes"<<endl;break;
            }
        }
        if(!ok)
            cout<<"No"<<endl;
    }
}

C:http://codeforces.com/contest/1365/problem/C

题意:

给出包含n个数的a[],b[]

找出一个k,使任意数向右或左移动k个单位。求移动后的b[]能与a[]进行的最大匹配数(i==j&&a[i]==b[j])

解析:

因为是一个数移动,其他数都要动,所以

统一向右移动即可

暴力找一下每个数,在a[]的位置和在b[]的位置的差值dis,求出现最多的dis即可。

比赛时交了一个919ms的,赛后进行了优化,但还是跑了700多秒

#include <cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
const int maxn=2e5+10;
int a[maxn],b[maxn];
int ds[maxn];
int main()
{

        int n;
        cin>>n;
        map<int,int>m1;
    //    map<int,int>m2;
        for(int i=1;i<=n;i++)
            cin>>a[i],m1[a[i]]=i;
        for(int i=1;i<=n;i++)
            cin>>b[i];
    //    map<int,int>m3;
        int maxx=0;
        for(int i=1;i<=n;i++)
        {
            int md;
            if(m1[b[i]]<i)
                md=m1[b[i]]+n-i;
            else
                md=m1[b[i]]-i;
            ds[md]++;    
            maxx=max(maxx,ds[md]);
        }
        
        cout<<maxx<<endl;
}

D:http://codeforces.com/contest/1365/problem/D

题意:

n*m的矩阵,包含:

空:.

墙:#

好人:G

坏人:B

上下左右走动

终点a[n][m]初始一定为空:'.'

墙不能走,G,B处和 '.' 处可以走

操作是把'.'变成墙'#',要求所有B不能到达终点,所有G可以到达终点,问是否能达到目的?

解析:

由于G,B处可以走,所以只要G,B出现相邻,那么如果此G能到达终点,B一定可以沿着G的路线到达终点,所以这个相邻情况一定是NO

其他情况,

先把B周围围死,再以终点为起点进行BFS,把终点能到达的位置全标记上。

再次遍历全图,如果某个位置为G,但是没有被标记,说明它不能到达终点,为NO

#include <cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=100;
char a[maxn][maxn];
int vis[maxn][maxn];
int dx[5]={0,0,-1,1};
int dy[5]={-1,1,0,0};
int n , m ;
struct node{
    int x,y;
};
int ok = 0;
void check(int x,int y)
{
    for(int i=0;i<4;i++)
    {
        int ddx=x+dx[i];
        int ddy=y+dy[i];
        if(ddx>=1&&ddx<=n&&ddy>=1&&ddy<=m)
        {
            if(a[ddx][ddy]=='.')
                a[ddx][ddy]='#';
            if(a[ddx][ddy]=='G')
            {
                ok=1;break;
            }
        }
    }
}
void bfs(int n,int m)
{
    queue<node>q;
    q.push((node){n,m});
    vis[n][m]=1;
    while(!q.empty())
    {
        node s=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int ddx=s.x+dx[i];
            int ddy=s.y+dy[i];
            if(ddx>=1&&ddx<=n&&ddy<=m&&ddy>=1&&!vis[ddx][ddy])
            {
                if(a[ddx][ddy]!='#')
                {
                    vis[ddx][ddy]=1;
                    q.push((node){ddx,ddy});
                }
            }
        }
    }
}
int main()
{    
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        memset(vis,0,sizeof(vis));
        ok=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                cin>>a[i][j];
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]=='B')
                {
                    check(i,j);
                }
            }
        }
        
        if(ok)
            {
                cout<<"No"<<endl;continue;
            }
    //    a[n][m]='.';
        if(a[n][m]!='#')
        bfs(n,m);    
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]=='G'&&!vis[i][j])
                {
                    ok=1;break;
                }
            }
            if(ok)
                break;
        }
        if(ok)
            cout<<"No"<<endl;
        else
            cout<<"Yes"<<endl;
    }
}

E:http://codeforces.com/contest/1365/problem/E

题意:

n个数的a[],

从中选取k个数,对这k个数转成二进制,位置一一对应从上到下排起来

如果某位置满足max(1,k-2)个1,sum就+2^i(i为第几位)

求最大的sum

解析:

max(1,k-2),当k<=3时,取得是1。所以k取0,1,2,3时,只要符合条件位有一个1,就没问题。所以k只要小于4,不管取几,对答案都没有影响。

当K>=4,max(1,k-2)=2,假设前3个数已经是最大解,那么加入第4个数,需要满足每位2个1才行,显然,求的sum可能会变小,没有必要。

sum加的只是2^i,每位几个1,与它无关,只要有1,就可以。所以k>3,对sum的影响,要么不变,要么减小。

所以只看k=3,就可以了

n^3暴力遍历即可,注意long long

这里用到了or: ' | ' 运算:只要有1,就是1。

#include <cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=600;
ll a[maxn];
int main()
{    
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    ll maxx=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
                maxx=max(maxx,a[i]|a[j]|a[k]);
        }
    }
    cout<<maxx<<endl; 
}
原文地址:https://www.cnblogs.com/liyexin/p/13067680.html