简直难到没朋友。

双向bfs + 剪枝。

剪枝策略:

对于2--5位置上的数,仅仅有当光标在相应位置时通过swap ,up。down来改变。那么当当前位置没有达到目标状态时,left和right无意义。

好了。仅仅剪掉这里就过掉了。。。

还有比較炫酷的方法实现枚举720种排列。

。。

然后状压什么的。。。

功力不够全然看不懂。

。。。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map> #pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 9999991 using namespace std; short int mark[1000000][7][2]; struct Q
{
int ans,sta,site,fl;
}; int s[10]; int pre[] = {1000000,100000,10000,1000,100,10,1};
// 0 1 2 3 4 5 6
inline int Cal(int num,int site,int ch)
{
int temp = (num/pre[site])%10 + ch;
if(0 <= temp && temp <= 9)
return num/pre[site-1]*pre[site-1] + temp*pre[site] + num%pre[site];
return num;
} inline int Swap(int num,int site,int m)
{
int t1 = (num/pre[site])%10;
int t2 = (num/pre[m])%10; if(t1 == t2)
return num; num = num/pre[site-1]*pre[site-1] + t2*pre[site] + num%pre[site];
num = num/pre[m-1]*pre[m-1] + t1*pre[m] + num%pre[m];
return num;
} bool Judge(int site,int a,int b)
{
if((a/pre[site])%10 == (b/pre[site])%10)
return true;
return false;
} int bfs(int a,int b)
{
memset(mark,-1,sizeof(mark)); queue<Q> q;
Q s,t; s.sta = a;
s.fl = 0;
s.ans = 0;
s.site = 1; mark[s.sta][s.site][s.fl] = 0;
q.push(s); s.sta = b;
s.ans = 0;
s.fl = 1; for(int i = 1;i <= 6; ++i)
{
s.site = i;
mark[s.sta][s.site][s.fl] = 0;
q.push(s);
} while(q.empty() == false)
{
t = q.front();
q.pop(); // printf("site = %2d sta = %6d fl = %2d ans = %2d\n",t.site,t.sta,t.fl,t.ans); if(mark[t.sta][t.site][t.fl^1] != -1)
{
return mark[t.sta][t.site][t.fl^1] + t.ans;
} s.fl = t.fl;
s.ans = t.ans+1; //left
s.sta = t.sta; if(t.site > 1 && (t.site < 2 || t.site > 5 || Judge(t.site,t.sta,t.fl == 0 ? b : a)))
{
s.site = t.site-1;
if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
}
} //right
if(t.site < 6 && (t.site < 2 || t.site > 5 || Judge(t.site,t.sta,t.fl == 0 ? b : a)))
{
s.site = t.site+1;
if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
}
} //up
s.sta = Cal(t.sta,t.site,1);
s.site = t.site;
if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
} //down
s.sta = Cal(t.sta,t.site,-1); if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
} //swap0
if(t.site != 1)
{
s.sta = Swap(t.sta,t.site,1); if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
}
} //swap1
if(t.site != 6)
{
s.sta = Swap(t.sta,t.site,6);
if(mark[s.sta][s.site][s.fl] == -1)
{
mark[s.sta][s.site][s.fl] = s.ans;
q.push(s);
}
}
}
return 0;
} int main()
{
//freopen("data.txt","r",stdin);
int a,b;
scanf("%d %d",&a,&b);
printf("%d\n",bfs(a,b)); return 0;
}

POJ 1184 聪明的打字员的更多相关文章

  1. (广搜)聪明的打字员 -- POJ --1184

    链接: http://poj.org/problem?id=1184 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#probl ...

  2. poj1184 聪明的打字员(BFS剪枝)

    http://poj.org/problem?id=1184 用字符串s存下数字,并把光标位置做一个字符加到s末尾,用map做标记状态是否出现过,然后bfs即可. 不剪枝是过不了的,考虑的两种交换操作 ...

  3. 聪明的打字员---poj1184(bfs)

    题目链接:http://poj.org/problem?id=1184 分析:首先可以发现有6*10^6种状态,比较多,不过搜索的时候可以去除一些无用的状态, 可以发现一个点的值(2-5)如果想要改变 ...

  4. poj 1184 广搜进阶题

    起初的想法果然就是一个6000000的状态的表示. 但是后面觉得还是太过于幼稚了. 可以看看网上的解释,其实就是先转换位置,然后再改变数字的大小. #include<iostream> # ...

  5. codevs 1733 聪明的打字员 (Bfs)

    /* Bfs+Hash 跑的有点慢 但是codevs上时间限制10s 也ok */ #include<iostream> #include<cstdio> #include&l ...

  6. poj 1184

    经典的宽搜题目,感觉最好的办法应该是双向广搜. 不过用简单的启发式搜索可以飘过. #include <iostream> #include <cstdio> #include ...

  7. poj练习题的方法

    poj1010--邮票问题 DFSpoj1011--Sticks dfs + 剪枝poj1020--拼蛋糕poj1054--The Troublesome Frogpoj1062--昂贵的聘礼poj1 ...

  8. poj很好很有层次感(转)

    OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 30 ...

  9. POJ题目分类推荐 (很好很有层次感)

    著名题单,最初来源不详.直接来源:http://blog.csdn.net/a1dark/article/details/11714009 OJ上的一些水题(可用来练手和增加自信) (POJ 3299 ...

随机推荐

  1. jquery mobile切换页面的几种方法

    jquery mobile切换页面的几种方法 - 不厚道青蛙之焦油潭 - 博客频道 - CSDN.NET jquery mobile切换页面的几种方法 分类: phonegap html5 2012- ...

  2. ubuntu 10.04安装qtcreator并汉化

    最近最的项目中需要做出来一个带有界面的demo,所以想到了用qt做个简单的demo! 于是在ubuntu上安装了qt,很简单apt-get apt-get install qtcreator 大概几百 ...

  3. linux设备驱动程序注冊过程具体解释

    Linux的驱动程序注冊过程,大致分为两个步骤: 模块初始化 驱动程序注冊 以下以内核提供的演示样例代码pci-skeleton.c,具体说明一个pci设备驱动程序的注冊过程.其它设备的驱动代码注冊过 ...

  4. 使用JDBC对数据库实现批处理操作

    本篇讲述如何使用JDBC对数据库实现批处理操作.很多时候单条SQL命令不能满足我们的需求,我们需要对数据库一次实现很多操作,需要发送一批SQL命令给数据库执行. 而JDBC也提供了相应的方法给我们实现 ...

  5. 【ASP.NET Web API教程】2.3.6 创建产品和订单控制器

    原文:[ASP.NET Web API教程]2.3.6 创建产品和订单控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 6 ...

  6. autotools入门笔记(一)

    GNU autotools作用:收集系统配置信息并自动生成Makefile文件. GNU autotools主要包括三个工具:autoconf.automake.libtool,还有很多辅助的工具,包 ...

  7. 设置静态IP

    设定IP $sudo vi/etc/network/interfaces autolo iface lo inet loopback 加入下面内容 autoeth0 iface eth0inet st ...

  8. 用 managedQuery() 时须要注意的一个陷阱

    Activity 里面提供了一个 managedQuery() 方法,依照 Android SDK 里面的说明,"the activity will manage its lifecycle ...

  9. ALV调用的几个标准函数

    ALV的调用主要由以下几个标准函数实现,所有函数的输入输出参数必须大写,否则系统会出现异常中止,相关函数如下: 1)REUSE_ALV_FIENDCATALOG_MERGE:根据内表结构返回FIELD ...

  10. VC中添加web控件的方法

    在VC中使用WebBrowser控件的两方法 黄森堂(vcmfc)著 ClassWizard方式: 1.创建包装类:View->ClassWizard->Add Class->For ...