点这里 打开题目链接   点击打开链接

题目就是我们玩过的推箱子;

一顿暴力广搜;加状态标记。状态压缩需要用到一个类似于康拓的思想来压缩;所以容易TLE,搜索就是用一个int型的数字来表示一个状态,

压缩的和代码

void set_C()
{
memset(C,,sizeof(C));
int i,j;
for(i=; i<=; i++)
{
C[i][]=;
for(j=; j<=; j++)
C[i][j]=C[i-][j-]+C[i-][j];// C数组是组合数,C n,m
}
} int binary_cantor(int num,int g)
{
int w,ans=,y=g;
for(int i=; i>=; i--)
{
if(num&(<<i))
{
ans+=C[i][g];
g--;
if(g==) break;
}
}
return ans;
}

值得注意判断死角是相邻的两个方向不能够移动。

剩下的在完整代码中说明。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#include <stdlib.h> using namespace std;
typedef long long LL;
const int INF=2e9+1e8;
const int MOD=1e9+;
const int MM=;
const int VIS=*+;
const int LEN=+;
int n,m,dir[][]= {{,},{,},{-,},{,-}};// 最好是让dir数组顺时针或者逆时针 方向转动
string Push_Sokoban;// 记录地图中哪些地方有枪
int C[][];//组合数
int aim; // 用一个二进制位记录仓库的位置
bool vis[VIS]; //标记状态的数组
struct point
{
int x,y;
};
struct node
{
int pos,step,stauts;
};
void set_C()// 递推打印组合数;
{
memset(C,,sizeof(C));
int i,j;
for(i=; i<=; i++)
{
C[i][]=;
for(j=; j<=; j++)
C[i][j]=C[i-][j-]+C[i-][j];
}
} int binary_cantor(int num,int g)//压缩状态; 表示num这个数有g位二进制位为1 返回的数字表示num这个数在他们的排列中第几小
{
int w,ans=,y=g;
for(int i=; i>=; i--)
{
if(num&(<<i))
{
ans+=C[i][g];
g--;
if(g==) break;
}
}
return ans;
}
bool is_out(int x,int y)// 是否越界
{
if(x>=&&x<n&&y>=&&y<m) return true;
return false;
}
/***************************/
//一维 与 二维 坐标的相互转化
int change(int x,int y)
{
return x*m+y;
}
int change(point p)
{
return p.x*m+p.y;
}
point change(int x)
{
point p;
p.x=x/m,p.y=x%m;
return p;
}
/****************************/
bool is_arrive(int box,int pos,int num)// 判断该状态是否来过
{
int temp=binary_cantor(box,num);
int a=pos*LEN+temp;
if(!vis[a])
{
vis[a]=;// 未来过该状态则需要标记一下
return true;
}
return false;
}
bool check_dead(int box,int bpos)// 是否进入死角,死角意味着, 该箱子未到仓库,且无法移动
{
point p=change(bpos);
for(int i=; i<; i++)
{
if(!is_out(p.x+dir[i][],p.y+dir[i][])||Push_Sokoban[change(p.x+dir[i][],p.y+dir[i][])]=='*')
{
if(!is_out(p.x+dir[(i+)%][],p.y+dir[(i+)%][])||Push_Sokoban[change(p.x+dir[(i+)%][],p.y+dir[(i+)%][])]=='*')
if(!(aim&(<<bpos))) return false;
}
}
return true;
} // 下面就是广搜核心了
int bfs(int pos,int box,int number)// 全局变量注意清零
{
node first,second;
first.step=,first.pos=pos,first.stauts=box;
queue<node>q;
memset(vis,,sizeof(vis));
q.push(first);
while(!q.empty())
{
first=q.front();
// cout<<bitset < sizeof(int)*8 > (first.stauts)<<endl;
// cout<<"@ "<<first.pos<<endl;
if(aim==first.stauts) return first.step;
q.pop();
for(int i=; i<; i++)
{
point p=change(first.pos);
int x=p.x+dir[i][],y=p.y+dir[i][];
int bx=p.x+*dir[i][],by=p.y+*dir[i][];
int box_pos=change(bx,by);
box=first.stauts;
pos=change(x,y);
if(is_out(x,y)&&Push_Sokoban[pos]!='*')
{
if((box&(<<pos))&&is_out(bx,by)&&!(box&(<<box_pos))&&Push_Sokoban[box_pos]!='*')// 该位置上有箱子
{
box=box&(~(<<pos)),box=box|(<<box_pos);
if(is_arrive(box,pos,number)&&check_dead(box,box_pos)) //
{
// printf("ren pos =%d x=%d y=%d\n",pos,change(pos).x,change(pos).y);
second.pos=pos,second.stauts=box,second.step=first.step+;
q.push(second);
}
}
else if(!(box&(<<pos))&&is_arrive(box,pos,number))
{
// printf("ren pos =%d x=%d y=%d\n",pos,change(pos).x,change(pos).y);
second.pos=pos,second.stauts=box,second.step=first.step+;
q.push(second);
}
}
}
}
return -;
}
/************************** 本题难点就在与状态压缩,如何给定一个数,给定二进
制位1的个数,快速判断第几小,有点康拓的感觉
*******************************************/
int main(void)
{
int ncase;
set_C();
cin>>ncase;
while(ncase--)
{
scanf("%d%d",&n,&m);
Push_Sokoban.clear();
int man_pos;
int box=,num=;
aim=;
for(int i=; i<n; i++)
{
string s;
cin>>s;
for(int j=; j<m; j++)
{
if(s[j]=='m') man_pos=i*m+j,s[j]='.';
else if(s[j]=='b') s[j]='.',box=box|(<<(i*m+j)),num++;
else if(s[j]=='w') s[j]='.',aim=aim|(<<(i*m+j));
else if(s[j]=='+') s[j]='.',box=box|(<<(i*m+j)),aim=aim|(<<(i*m+j)),num++;
}
Push_Sokoban+=s;
}
//cout<<bitset < sizeof(int)*8 > (aim) <<endl;
printf("%d\n",bfs(man_pos,box,num));
}
return ;
}

康拓的题目,详见  点击打开链接

推箱子 Sokoban(华中农业比赛)的更多相关文章

  1. three.js 制作一个三维的推箱子游戏

    今天郭先生发现大家更喜欢看我发的three.js小作品,今天我就发一个3d版本推箱子的游戏,其实webGL有很多框架,three.js并不合适做游戏引擎,但是可以尝试一些小游戏.在线案例请点击博客原文 ...

  2. OC推箱子

    #include<stdio.h> #include<stdlib.h> int main(void) { char sr;//存储用户输入的指令 //绘制地图 char a[ ...

  3. c语言游戏推箱子

    前两天做了推箱子小游戏,看似简单的一个小游戏背后却 有巨大的秘密,这秘密就是一大堆逻辑. 自从学习了函数过后,的确是解决了很多问题,而且调用很方便,尽管我现在都不是很会调用. 写完一个函数,准备测试一 ...

  4. JavaScript写一个小乌龟推箱子游戏

    推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用 ...

  5. 用C#制作推箱子小游戏

    思路分析: 一.制作一个地图 二.地图中放置墙.箱子.人.目标等 三.让小人动起来完成推箱子动作 游戏制作: 1.按照上述地图制作一个地图  (12行×13列) 地图可以看做是行和列组成的,即可以看做 ...

  6. hdu.1254.推箱子(bfs + 优先队列)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  7. [游戏模版17] Win32 推箱子 迷宫

    >_<:Here introduce a simple game: >_<:resource >_<:only can push a box and finally ...

  8. [转]Flash ActionScript2.0面向对象游戏开发-推箱子

    本文转自:http://www.alixixi.com/Dev/W3C/Flash/2007/2007070868666.html 概述: Flash ActionScript2.0是一种面向对向的编 ...

  9. c#部分---网吧充值系统;简易的闹钟;出租车计费;简单计算器;对战游戏;等额本金法计算贷款还款利息等;随机生成10个不重复的50以内的整数;推箱子;

    网吧充值系统namespace ConsoleApplication1 { class Program { struct huiyuan { public string name; public st ...

随机推荐

  1. sqlplus 命令 错误

    SP2-1503: 无法初始化 Oracle 调用界面 用管理员运行就可以了

  2. OO第三单元作业小结

    一.JML理论基础及应用工具链情况 理论基础 1.JML表达式 \result:表示方法执行后的返回值. \old(expr):表示一个表达式expr在相应方法执行前的取值. \foall:全称量词修 ...

  3. HDFS api操作

    import java.net.URI;import java.util.Iterator;import java.util.Map.Entry; import org.apache.hadoop.c ...

  4. K8S label 操作

    在部署完成 node 节点集群之后,为了更灵活的操控 node 节点,有时候需要对 node 节点进行对各个 node 节点进行 lable 标签标记. 查看各个节点的信息 [root@porxy02 ...

  5. Mac装Win10后没有无线网络的处理

    在“文件资源管理器”中找到“此电脑”,打开,看到“设备与驱动管理器”,找到Bootcamp文件夹,点击进入,运行setup,之后重启就好了.

  6. stl_内存基本处理工具

    内存基本处理工具 STL定义5个全局函数.作用于初始化空间上.各自是:用于构造的construct(),用于析构的destroy(),uninitialized_copy(),uninitialize ...

  7. 聊聊高并发(二十四)解析java.util.concurrent各个组件(六) 深入理解AQS(四)

    近期总体过了下AQS的结构.也在网上看了一些讲AQS的文章,大部分的文章都是泛泛而谈.又一次看了下AQS的代码,把一些新的要点拿出来说一说. AQS是一个管程.提供了一个主要的同步器的能力,包括了一个 ...

  8. google protocol buffer的原理和使用(一)

    一.简单的介绍      Protocol buffers是一个用来序列化结构化数据的技术,支持多种语言诸如C++.Java以及Python语言.能够使用该技术来持久化数据或者序列化成网络传输的数据. ...

  9. 李洪强iOS开发之-入门指南

    李洪强iOS开发之-入门指南 1零基础小白如何进行iOS系统学习 首先,学习目标要明确:其次,有了目标,要培养兴趣,经常给自己一些正面的反馈,比如对自己的进步进行鼓励,在前期小步快走:再次,学技术最重 ...

  10. Creo二次开发--内存清理函数

    我们在处理模型文件时,总会遇到内存环境的清除问题.一个干净的Creo工作环境.是保证工作能顺利完毕的保障. ProMdlEraseNotDisplayed()函数提供了清除未显示模型的功能. 当须要循 ...