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; }
标签:思维,ddx,暴力,int,Codeforces,cin,vis,maxn,include 来源: https://www.cnblogs.com/liyexin/p/13067680.html