Codeforces Round #648 (Div. 2)

Problem A. Matrix Game

A. Matrix Game

题意:给你有0和1的矩阵,0代表未被声明的点,1代表已声明的点,有两个人进行博弈,每个人每次只能选择未声明的点,并且未声明的点所在的行和列不能有已经声明的点。到最后,如果有一个人无法选取未声明的点,那么就代表他失败。最后答案输出获胜人的名字。
题解:统计出不包含1的行数和列数,最后取行列的最小值,也就是两个人博弈时能选取点的个数,如果整除2则第二个人赢,否则第一个人赢。

#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define inf (1LL<<62)-1
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double lb;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const long double PI = acos(-1);
const int N = 5e3+10;
const int mod=998244353;

int a[55][55];
int hang[55],lie[55];
int main(int argc, char *argv[]) {
	int t;
	cin >> t;
	while(t--)
	{
		memset(hang, 0, sizeof(hang));
		memset(lie, 0, sizeof(lie));
		int n,m;
		cin >> n >> m;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++) cin >> a[i][j];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
			{
				if(a[i][j])
				{
					hang[i]=1;
					lie[j]=1;
				}
			}
		int hh=0,li=0;
		for(int i=0;i<n;i++)
			if(hang[i]==0) hh++;
		for(int i=0;i<m;i++)
			if(lie[i]==0) li++;
		if(min(hh,li)%2) cout << "Ashish" << endl;
		else cout << "Vivek" << endl;
	}
}

Problem B. Trouble Sort

B. Trouble Sort

题解:
如果b中存在两个不一样的类型,那么它们一定可以交换成非递减序列。
如果b里面类型一致,那么只有a为非递减才满足条件。

#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define inf (1LL<<62)-1
using namespace std;
extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double lb;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const long double PI = acos(-1);
const int N = 5e3+10;
const int mod=998244353;

int a[505],b[505];

void solve()
{
	int n;
	cin >> n;int cnt1=0,cnt2=0;
	for(int i=0;i<n;i++) cin >> a[i];
	for(int i=0;i<n;i++) 
	{
		cin >> b[i];
		if(b[i]) cnt1=1;
		else cnt2=1;
	}
	if(cnt1 && cnt2)
	{
		cout << "YES" << endl;
		return ;
	}
	for(int i=1;i<n;i++)
	{
		if(a[i]<a[i-1])
		{
			cout << "NO" << endl;
			return ;
		}
	}
	cout << "YES" << endl;
}
int main(int argc, char *argv[]) {
	int t;
	cin >> t;
	while(t--)
	{
		solve();
	}
}

Problem C. Rotation Matching

C. Rotation Matching

题解:由题可知,如果直接暴力的话,时间复杂度为: O(n^2),所以得换一种思路。
将位移作为一种标准,即b数组每个数字移动到与a相同时所需的位移,最后统计相同位移出现次数最多的即答案。

#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define inf (1LL<<62)-1
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double lb;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const long double PI = acos(-1);
const int N = 2e5+10;
const int mod=998244353;

int a[N],b[N],book[N];
map<int,int> mp;

int main(int argc, char *argv[]) {
	int n;
	cin >> n;
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	for(int i=0;i<n;i++) scanf("%d",&b[i]);
	for(int i=0;i<n;i++) mp[a[i]]=i;
	for(int i=0;i<n;i++) book[(i-mp[b[i]]+n)%n]++;
	int ans=0;
	for(int i=0;i<n;i++) ans=max(ans,book[i]);
	cout << ans << endl;
}

Problem D. Solve The Maze

D. Solve The Maze

题解:
搜索题,但奈何自己的搜索过于菜,写了个记忆化搜索始终过不了,花了一天时间没搞出来。最后看题解才会了,感觉思路差不多,但“人家”的就是能过。

  1. 首先可以对一些“特殊情况”进行特判:
    如果没有G,那么一定为Yes。
    如果G和B相邻,那么一定为No。
  2. 接下来,先进行预处理,很明显将B的上下左右四个为“ . ”点封住是最优的,注意有可能将终点封住,所以需要特判,如果将终点封住则为No。然后从(n-1,m-1)终点进行dfs遍历,如果能遍历每一个G点,那么符合要求。否则No。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>

int nextp[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
char g[55][55];
bool flag;
int vis[55][55],cnt=0,n,m;

void dfs(int x,int y)
{
    if(g[x][y]=='G')
        cnt++;
    for(int i=0;i<4;i++)
    {
        int tx=x+nextp[i][0];
        int ty=y+nextp[i][1];
        if(tx<0 || tx>=n || ty<0 || ty>=m) continue;
        if((g[tx][ty]=='.' || g[tx][ty]=='G') && !vis[tx][ty])
        {
            vis[tx][ty]=1;
            dfs(tx, ty);
        }
    }
}
void solve()
{
    cnt=0;
    cin >> n >> m;
    for(int i=0;i<n;i++) cin >> g[i];
    int num=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(g[i][j]=='G') num++;
            if(g[i][j]=='B')
            {
                for(int k=0;k<4;k++)
                {
                    int tx=i+nextp[k][0];
                    int ty=j+nextp[k][1];
                    if(tx<0 || tx>=n || ty<0 || ty>=m) continue;
                    if(g[tx][ty]=='G')
                    {
                        cout << "No" << endl;
                        return ;
                    }
                    if(g[tx][ty]=='.') g[tx][ty]='#';
                }
            }
        }
    }
    if(!num)
    {
        cout << "Yes" << endl;
        return ;
    }
    if(g[n-1][m-1]=='#')
    {
        cout << "No" << endl;
        return ;
    }
    dfs(n-1, m-1);
    if(cnt==num)
    {
        cout << "Yes" << endl;
        return ;
    }
    cout << "No" << endl;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        memset(vis, 0, sizeof(vis));
        solve();
    }
}

Problem E. Maximum Subsequence Value

E. Maximum Subsequence Value

题解:由题可知,答案的结果就是选取这k个数的“或运算”结果。

  1. 当选取子序列个数≤3时,每个数都能选;
  2. 倘若个数大于3时,你必须选取已选3个数"或运算"结果二进制位为1的数,假如已选3个数"或运算"结果二进制位为11011,那么我就不能选第三位为1的数,因为已经有3个不满足条件,选中间一位为1,就不可能满足max(1,(k-2))条件。所以,只需在这些数中找任意三个数或运算结果最大的值即可,由于n不大,可以暴力解决。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>

ll a[505];
map<int,int>mp;
int main()
{
    int n;
    cin >> n;
    for(int i=0;i<n;i++)
        cin >> a[i];
    ll ans=-1;
    for(int i=0;i<n;i++)
        for(int j=i;j<n;j++)
            for(int k=j;k<n;k++)
                ans=max(ans, (a[i]|a[j]|a[k]));
    cout << ans << endl;
}

Problem F. Swaps Again

F. Swaps Again

题解:没想到F题也是个思维,但是不好想。
无论怎么交换,对称的两个数a[i]和a[n+1-i]永远是对称的,一一对应的。所以我们可以将(a[i]和a[n+1-i])打包,将b的(b[i]和b[n+1-i])打包,将这两个打包数组排序。最后判断是否一致即可。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>

int a[505],b[505];
vector<pair<int, int> >mp,mp1;
void solve()
{
    mp.clear();
    mp1.clear();
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) cin >> a[i];
    for(int i=1;i<=n;i++) cin >> b[i];
    if(n%2 && a[(n+1)/2]!=b[(n+1)/2])
    {
        cout << "No" << endl;
        return ;
    }
    for(int i=1;i<=n/2;i++) mp.push_back(make_pair(min(a[i],a[n+1-i]),max(a[i],a[n+1-i])));
    for(int i=1;i<=n/2;i++) mp1.push_back(make_pair(min(b[i],b[n+1-i]),max(b[i],b[n+1-i])));
    sort(mp.begin(),mp.end());
    sort(mp1.begin(),mp1.end());
    for(int i=0;i<n/2;i++)
    {
        if(mp[i]!=mp1[i])
        {
            cout << "No" << endl;
            return ;
        }
    }
    cout << "YEs" << endl;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值