博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ZJOI2007]矩阵游戏【bzoj1059/洛谷1129】/ [HEOI2016/TJOI2016]游戏
阅读量:4467 次
发布时间:2019-06-08

本文共 3399 字,大约阅读时间需要 11 分钟。


 

QQ是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个N \times NN×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:

行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)

列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)

游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。

对于某些关卡,小QQ百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小QQ决定写一个程序来判断这些关卡是否有解。

         

       目标状态要求矩阵的主对角线上的格子均为黑色。

        即是(1,1),(2,2),(3,3)......(n,n)皆匹配;

        如果原图满足每行和每列都匹配,那么通过交换,一定可以换成上面这种情况。

         所以拆行和列跑一个最大二分图匹配,并判断匹配数是否等于n即可。

 

         代码见

       

#include
#define re register int#define maxn 200+5using namespace std;int t,n;int ma[maxn][maxn];inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*f;}int ans,match[maxn];bool ed[maxn][maxn],vis[maxn];bool dfs(int x){for(re i=1;i<=n;i++)if(!vis[i]&&ed[x][i]){vis[i]=true;if(!match[i]||dfs(match[i])){match[i]=x;return true;}}return false;}int main(){ios::sync_with_stdio(false);t=read();while(t--){ans=0;memset(match,0,sizeof(match));memset(ed,false,sizeof(ed));n=read();for(re i=1;i<=n;i++)for(re j=1;j<=n;j++)ed[i][j]=read();for(re i=1;i<=n;i++){memset(vis,false,sizeof(vis));ans+=dfs(i);}if(ans==n) cout<<"Yes"<
View Code

 


 

[HEOI2016/TJOI2016]游戏

 

在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图*xx*,这个地图上最多只能放置一个炸弹。给出另一个1*4的网格地图*x#*,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最多能放置多少炸弹。

       显然 这道题和上面的题极为相像。

      需要处理的是把联通的序列(包括空地和软石头)行和列分别处理,进行二分图匹配。

       

#include
#define re register int#define maxn 50+5#define maxn1 2500+5using namespace std;int n,m;int cnt,tot;char ma[maxn][maxn];int row[maxn][maxn],col[maxn][maxn];struct edge{ int nex,to;}ed[maxn1];int head[maxn1];inline int read(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch)){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f;}inline void write(int x){ if(x<0){ putchar('-'); x=-x; } if(x>9) write(x/10); putchar(x%10+'0'); }int ans,match[maxn1];bool vis[maxn1];bool dfs(int x){ for(re e=head[x],v;e;e=ed[e].nex) { if(!vis[v=ed[e].to]) { vis[v]=true; if(!match[v]||dfs(match[v])) { match[v]=x; return true; }} } return false;}void add(int x,int y) { ed[++cnt].nex=head[x]; ed[cnt].to=y; head[x]=cnt;}char get(){ char ch; while((ch=getchar())!='#'&&ch!='*'&&ch!='x'); return ch;}int main(){ ios::sync_with_stdio(false); n=read(); m=read(); ; for(re i=1;i<=n;i++) for(re j=1;j<=m;j++) ma[i][j]=get(); for(re i=1;i<=n;i++) for(re j=1;j<=m;j++){ if(ma[i][j]=='#') continue; if(j==1||ma[i][j-1]=='#') tot++; row[i][j]=tot; } for(re i=1;i<=m;i++) for(re j=1;j<=n;j++){ if(ma[j][i]=='#') continue; if(j==1||ma[j-1][i]=='#') tot++; col[j][i]=tot; } for(re i=1;i<=n;i++) for(re j=1;j<=m;j++) { if(ma[i][j]!='*') continue; add(row[i][j],col[i][j]); } for(re i=1;i<=tot;i++) { memset(vis,false,sizeof(vis)); ans+=dfs(i); } write(ans); return 0;}
View Code

 

转载于:https://www.cnblogs.com/3200Pheathon/p/10704041.html

你可能感兴趣的文章
专题:动态内存分配----基础概念篇
查看>>
Codeforces Round #426 (Div. 2) (A B C)
查看>>
The Most Simple Introduction to Hypothesis Testing
查看>>
UVA10791
查看>>
P2664 树上游戏
查看>>
jQuery 停止动画
查看>>
Sharepoint Solution Gallery Active Solution时激活按钮灰色不可用的解决方法
查看>>
教你50招提升ASP.NET性能(二十二):利用.NET 4.5异步结构
查看>>
lua连续随机数
查看>>
checkstyle使用介绍
查看>>
会了这十种Python优雅的写法,让你工作效率翻十倍,一人顶十人用!
查看>>
二维码图片生成
查看>>
在做操作系统实验的一些疑问
查看>>
Log4J日志配置详解
查看>>
NameNode 与 SecondaryNameNode 的工作机制
查看>>
Code obfuscation
查看>>
大厂资深面试官 带你破解Android高级面试
查看>>
node.js系列(实例):原生node.js实现接收前台post请求提交数据
查看>>
SignalR主动通知订阅者示例
查看>>
用python实现矩阵转置
查看>>