原题地址:http://acm.fzu.edu.cn/problem.php?pid=1892

Problem 1892 接水管游戏

Accept: 108    Submit: 498
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

接水管游戏的规则如下:
1、在N*N大小的方格上有两个特别的水管,分别为进水口和出水口;
2、有7种1*1大小的水管需要放在这N*N大小的方格内,使得水流能够从进水口经过这些水管流到出水口;
3、当水流流到了出水口或者水流在流到出水口之前流出了水管,那么游戏就结束了;
4、游戏的分数为水流经过水管的数目(除了进水口和出水口);
5、游戏中有四个方向,分别表示东南西北,可用数字编号说明水管中水流的方向,1表示可以向东流,2表示可以向南流,4表示可以向西流,8表示可以向北流;
6、七种水管的形状如下: :编号为15;:编号为9;:编号为6; :编号为3; :编号为12; :编号为10; :编号为5;
7、进水口的编号需要再加上16,出水口的编号需要再加上32,进水口和出水口中的水流只有一个方向,游戏中有且只有一个进水口和一个出水口;
8、每一时刻,水流都会沿着水管的水流方向流到相邻的方格之中,如果该方格没有水管或者水管接头不对应,那么水流将流出水管。
现在水管已经接好了,请你计算出在当前情况下,能够得到的分数。

Input

输入数据第一行为一整数T,表示有T组输入数据。每组输入数据的第一行为一个整数N(5≤N≤50),表示方格的大小,以下有N行,每行有N个数字Mij(1≤i,j≤N),表示第i行第j列方格中的水管编号,Mij=0表示该方格没有水管。

Output

对于每组数据,输出一行一个整数,表示能够得到的分数。

Sample Input

253 5 5 6 010 3 5 15 610 10 0 10 4010 9 5 12 189 5 5 5 1253 5 5 6 010 0 0 15 610 10 0 0 4010 9 5 12 189 5 5 5 12

Sample Output

1814

Hint

Source

福州大学第七届程序设计竞赛

这题一看就能知道是BFS,而且数据小,不会超时。但是接口的问题怎么处理,这个是重点。

题目很明显,管子就是状态压缩。题目第5点:游戏中有四个方向,分别表示东南西北,可用数字编号说明水管中水流的方向,1表示可以向东流,2表示可以向南流,4表示可以向西流,8表示可以向北流。1,2,4,8就是二进制数的4个位,编号15的管子,就是1+2+4+8=15,说明水管通向东南西北四个方向。同理,编号为9的管子,1+8=9,通向东和北。如此类推。

那么问题来了,分析一个管子通向哪几个方向,要怎么实现?之前学过点状压基础的就能知道,用位运算操作。

位运算:<<,左移 位运算,将数的二进制数向左移n位,左边的舍弃,右边补0 。  1<<n就是将1向左移动n位,左边舍弃,右边补0,其数值上等效于1*(2^n)。比如,1<<3,本来1的二进制数是0001,左移3位后,变为1000,等于8,2^3 。

位运算:&,且 位运算,对两个数的二进制数按位进行且运算,同为1,则该位为1 ,否则为0。如下:

00101
11100
----------------
00100

那么,结合这两个运算就能知道,管子通往哪几个方向。实现代码如下:

for(i=0; i<4; i++)
{
        if(  ( n&(1<<i) ) >0 )
        {

// 对应的二进制第 i 位就是1,就是这个位代表的方向可以流通

}

}

那么接下来,判断相邻的两个管子能不能接上,也就好办了。就是先判断管子通向哪个方向,然后判断那个方向的相邻管子也可以通向反方向。

左边管子方向朝东,它东边的管子可以通向西,那么它们就连通了。实现代码如下:

// 地图用二维的 int 储存

int map[50][50] ;

// 定义结构体,now,表示当前坐标;

// 用来移动的数组

int xx[4]= {0,1,0,-1};
int yy[4]= {1,0,-1,0};

for(i=0; i<4; i++)
{
if(  (maps[now.x][now.y]&(1<<i)  ) >0  )
{
        f(  (maps[ now.x+xx[i] ]  [ now.y+yy[i] ]  )  &  ( 1<<( (2+i)%4) ) ) >0  )
        {

//  连通!!(有没有感觉酱紫很燃~2333)

}

}

}

会了这些之后,再用BFS就没问题了~但是位运算让我很头大,细节问题让我调试了很久,比赛时没做出来,当天晚上改到凌晨1点多,但依然没对,还是第二天改对的……

AC代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;int maps[50][50];
bool book[50][50];
int xx[4]= {0,1,0,-1};
int yy[4]= {1,0,-1,0};
int t,n;
int x1,x2,y3,y2,i,j;
int flag=0;
int sum=0;
int k=0;
int num=0;struct node
{int x,y,com,step;
};
node now;
node next;
queue <node> qq;int main()
{scanf("%d",&t);while(t--){scanf("%d",&n);{num=0;// 注意,入口和出口都只有一个方向。减去16或32就是管子的出入口方向for(i=0; i<n; i++){for(j=0; j<n; j++){scanf("%d",&maps[i][j]);if(maps[i][j]>=32){maps[i][j]-=32;x2=i;y2=j;}else if(maps[i][j]>=16){maps[i][j]-=16;x1=i;y3=j;}if(maps[i][j]!=0){num++;}}}/*for(int i=0;i<n;i++){for(int j=0;j<n;j++){printf("%d ",maps[i][j]);}printf("\n");}// */next.x=x1;next.y=y3;next.step=0;flag=0x3f3f3f3f;//大于10^9且在int范围内,挺好用的一个最大值sum=0;for(i=0; i<4; i++){if((maps[x1][y3]&(1<<i))>0){next.com=(i+2)%4;//判断起始点的入水方向(起始点出水方向的反方向),以备后面使用//printf("%d\n",next.com);break;}}qq.push(next);memset(book,0,sizeof(book));while(!qq.empty()){now=qq.front();qq.pop();//printf("$%d\n",k++);//判断两步内是否会结束游戏(到终点,或者水流到管子外)for(i=0; i<4; i++){if((maps[now.x][now.y]&(1<<i))>0)//找到所有方向//不为终点,不越界,并且能连通if( ((now.x+xx[i])!=x2||(now.y+yy[i])!=y2) && ((now.x+xx[i])>=0) && ((now.x+xx[i])<n) && ((now.y+yy[i])>=0) && ((now.y+yy[i])<n)  && ((maps[now.x+xx[i]][now.y+yy[i]])&( 1<<((2+i))%4) )>0){for(j=0; j<4; j++)//下一步依旧不为终点,不越界,能连通{if((maps[now.x+xx[i]][now.y+yy[i]]&(1<<j))>0)if( ((now.x+xx[i]+xx[j])!=x2||(now.y+yy[i]+yy[j])!=y2) && ((now.x+xx[i]+xx[j])>=0) && ((now.x+xx[i]+xx[j])<n) && ((now.y+yy[i]+yy[j])>=0) && ((now.y+yy[i]+yy[j])<n)  && ((maps[now.x+xx[i]+xx[j]][now.y+yy[i]+yy[j]])&( 1<<((2+j)%4)) )>0){}else//否则标记步数,并且步数取最小值{flag=min(flag,now.step+1);//printf("^^%d\n",flag);}}}else//否则标记结束时刻的步数{flag=min(flag,now.step);//printf("^%d\n",flag);}}for(i=0; i<4; i++){if(((maps[now.x][now.y]&(1<<i))>0)&&(now.com!=i))//除了进水方向的出水方向(水不能从原路返回){//下一个管子没流到过,不为终点不越界并且可以连通if(!book[now.x+xx[i]][now.y+yy[i]] && ((now.x+xx[i])!=x2||(now.y+yy[i])!=y2) && ((now.x+xx[i])>=0) && ((now.x+xx[i])<n) && ((now.y+yy[i])>=0) && ((now.y+yy[i])<n)  && ((maps[now.x+xx[i]][now.y+yy[i]])&( 1<<((2+i)%4)) )>0 ){//printf("!!%d %d\n",now.x+xx[i],now.y+yy[i]);sum++;//答案++book[now.x+xx[i]][now.y+yy[i]]=1;//标记next.x=now.x+xx[i];next.y=now.y+yy[i];next.com=(i+2)%4;next.step=now.step+1;if(next.step<=flag)//下一步不会到终点,不会越界流出,那么才压入队列。flag在之前已经判断过,为游戏结束的步数{qq.push(next);//printf("%d %d %d\n",now.x+xx[i],now.y+yy[i],now.step);//getchar();}}}}}printf("%d\n",sum);while(!qq.empty()){qq.pop();}}}return 0;
}
/*
给你多提供一组数据测试使用~不用谢~我叫红领巾~
Simple input:
4
4
18 15 15 15
9 15 15 15
15 15 15 15
15 15 15 40
5
3 5 5 6 0
10 3 5 15 6
10 10 0 10 40
10 9 5 12 18
9 5 5 5 12
5
3 5 5 6 0
10 0 0 15 6
10 10 0 0 40
10 9 5 12 18
9 5 5 5 12Simple output:
10
18
14
*/

最后,女神镇宅~

FZU1892接水管游戏-BFS加上简单的状态压缩和位运算处理相关推荐

  1. python写整数逆位运算_简单了解python的一些位运算技巧

    前言 位运算的性能大家想必是清楚的,效率绝对高.相信爱好源码的同学,在学习阅读源码的过程中会发现不少源码使用了位运算.但是为啥在实际编程过程中应用少呢?想必最大的原因,是较为难懂.不过,在面试的过程中 ...

  2. 动态规划+BFS+DFS+回溯+红黑树+排序+链表+位运算(B站优质学习资源链接,后续会继续更新)

    动态规划 正月点灯笼(UP主) 个人主页 https://space.bilibili.com/24014925/channel/detail?cid=12580 动态规划第一讲 https://ww ...

  3. NKU两题简单题解析(递归分析与位运算技巧)

    题目:http://acm.nankai.edu.cn/p1002.html 题意:对给定的f(n),当 n>=50025002 的时候,f(n)=n-5:当 n<50025002 的时候 ...

  4. java游戏将相_(Java)算法——位运算基础及基本应用

    位运算基础及基本应用 在处理整形数值时,可以直接对组成整形数值的各个位进行操作.这意味着可以使用屏蔽技术获得整数中的各个位(??) 位运算是针对整数的二进制进行的位移操作 整数 32位 , 正数符号为 ...

  5. hdu 1429 胜利大逃亡(续) bfs+状态压缩

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. 战棋游戏中的简单策略方法:基于群表示论的思想

    战棋游戏中的简单策略方法:基于群表示论的思想 最近在开发一款自娱自乐的基于上世纪30年代历史背景的战棋游戏,需要为其设计一个策略算法,我一开始就想可能用比较传统的动态规划,恰逢本周周一周二中科院数学所 ...

  7. c语言写拼图游戏算法,[原创]拼图游戏移动算法,简单易懂

    [原创]拼图游戏移动算法,简单易懂 这是我第一次发表关于算法的贴子, 希望大家支持下 原理:判断用户点击的按扭的X或Y坐标是否与移动按扭相同, 并且移动按扭的X,Y坐标是否与用户点击按扭相邻. 拼图游 ...

  8. 【含源码】用python做游戏有多简单好玩

    有很多同学问我还有其他什么小游戏吗,游戏是怎么做的,难不难.我就用两篇文章来介绍一下,如何使用Python做游戏. 兔子与灌 俄罗斯方块 休闲五子棋 走迷宫 推箱子 消消乐 超多小游戏玩转不停↓  更 ...

  9. 一日一技:用Python做游戏有多简单

    自从表白代码发了以后,有很多同学问我除了这种表白的,还有其他什么小游戏吗,游戏是怎么做的,难不难.我就用两篇文章来介绍一下,如果使用Python做游戏. 兔子与灌 俄罗斯方块 休闲五子棋 走迷宫 推箱 ...

  10. 用Python做游戏有多简单

    许多开发者都曾梦想过开发一款属于自己的游戏,其实用Python就可以轻松实现.下图就是我用PyGame开发的一款简易游戏. 这篇文章我会给大家介绍,如何用PyGame实现一个在地图上移动的小猪. 贴图 ...

最新文章

  1. CXF wsdl2java 生成java代码供客户端使用
  2. 尝鲜:windows 7 来了
  3. 转: jdbc连接数据库需要注意和出错的地方
  4. 【组合数学】指数生成函数 ( 指数生成函数求解多重集排列示例 )
  5. pivotx的entry和page内容里的日期格式修改
  6. JS关于辅助函数inherit()的小问题
  7. Open×××多处理之-为什么不
  8. SQL2014 MySQL_SQL Server 2014 Express 官方免费版下载
  9. 威纶触摸屏485轮询通讯_威纶通触摸屏与PLC实现一机多屏通讯方法
  10. godaddy无法修改域名服务器,godaddy的DNS A记录不能修改原因
  11. 对 “悟空拼音”学习软件的教学过程优化分析
  12. linux内核代码_解决Linux内核代码审阅者短缺的问题
  13. 分享 | 自动驾驶现代百年史:从汽车工业的“白日梦”谈起
  14. 美林公司的尽职调查应用程序被选入Deloitte Tohmatsu的并购咨询解决方案
  15. php 交换机 密码,S5100系列交换机使用正确的用户名和密码进行SSH登录时提示错误的解决方法...
  16. CPU使用率和负载区别及分析
  17. Reflector反编译.NET文件后修复
  18. [导入]心若一动 泪就一行(转)
  19. python递归算法 - 汉诺塔问题
  20. Spring Messaging 远程代码执行漏洞分析(CVE-2018-1270)

热门文章

  1. 多御浏览器安卓版有哪些地方值得下载使用?
  2. 大学c语言机试是老师阅卷么,最近,我们找了一些老师聊了聊
  3. APM直升机调试记录
  4. 【CF724F】Uniformly Branched Trees 动态规划
  5. smartbi连接mysql数据库_数据源连接 - Smartbi V7 帮助中心 - Smartbi 在线知识中心
  6. 10年的工作经验?还是1个经验反复用了10年?
  7. Automatic Lip-reading with Hierarchical Pyramidal Convolution and Self-Attention for Image Sequences
  8. WAF绕过技术系列文章(一)
  9. zabbix三种常用报警方式:邮件、微信和短信报警
  10. 网络创业者如何通过自己建站迈出躺赚第一步?