poj 1198 / hdu 1401 Solitaire (记忆化搜索+meet in middle)

题目大意:给你一个8*8的棋盘,上面有四个棋子,给你一个初始排布,一个目标排布,每次移动,可以把一个棋子移动到一个相邻的空位,或者跨过1个相邻的棋子,在保证棋子移动不超过8次的情况下,问能否把棋盘上的棋子由初始排布变成目标排布

8*8的棋盘,刚好不爆ull,状压那些位置有棋子

然后从初始状态开始,暴搜出当前状态下,移动一个棋子之后所有可能到达的状态

直接搜,总状态数是8^8,此外还有常数,会爆

由于给定了目标排布,考虑meet in middle

从起始状态和目标状态各搜4步即可

为了防止爆栈,同时为了好写好调,最好用bfs

具体实现呢,可以开两个队列正反同时bfs,搜到合法结果就break掉,可以减少很多常数

开2个map,表示正/反着跑能否到达状态s,如果能到达,则mp[s]=1

以正着搜为例,当前从que1中取出的状态为s,能到达的下一个状态为t,如果t出现在map1中,就不必在推入que1了,如果t出现在map2中,说明存在合法状态,break掉输出YES

代码好长啊..但在搜索题里算短的了

  1 #include <map>
  2 #include <queue>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define NN 5010
  7 #define MM 2000
  8 #define maxn 200
  9 #define ll long long
 10 #define uint unsigned int
 11 #define ull unsigned long long
 12 using namespace std;
 13
 14 int id[10][10];
 15 int xx[4]={-1,0,1,0};
 16 int yy[4]={0,1,0,-1};
 17 ull bin[100];
 18 int ax[5],ay[5],bx[5],by[5];
 19 struct node{
 20     ull s;int c;
 21     friend bool operator < (const node &s1,const node &s2)
 22         {return s1.s<s2.s;}
 23     node(ull s,int c):s(s),c(c){}
 24     node(){}
 25 };
 26 map<ull,int>mp[2];
 27 int check(int x,int y,ull s)
 28 {
 29     if(x<1||y<1||x>8||y>8)return 0;
 30     if(s&bin[id[x][y]]) return 2;
 31     return 1;
 32 }
 33
 34 int main()
 35 {
 36     //freopen("t2.in","r",stdin);
 37     for(int i=1;i<=8;i++)
 38         for(int j=1;j<=8;j++)
 39             id[i][j]=8*(i-1)+j-1;
 40             //px[id[i][j]]=i,py[id[i][j]]=j;
 41     bin[0]=1;
 42     for(int i=1;i<=63;i++)
 43         bin[i]=bin[i-1]<<1;
 44     while(scanf("%d%d%d%d",&ax[1],&ay[1],&ax[2],&ay[2])!=EOF)
 45     {
 46     scanf("%d%d%d%d",&ax[3],&ay[3],&ax[4],&ay[4]);
 47     scanf("%d%d%d%d",&bx[1],&by[1],&bx[2],&by[2]);
 48     scanf("%d%d%d%d",&bx[3],&by[3],&bx[4],&by[4]);
 49     queue<node>q[2];
 50     ull s=0,t=0;
 51     int cnt=0,fx,fy,fl,nt;
 52     for(int i=1;i<=4;i++)
 53         s|=bin[id[ax[i]][ay[i]]];
 54     mp[0][s]=1;
 55     q[0].push(node(s,0));s=0;
 56     for(int i=1;i<=4;i++)
 57         s|=bin[id[bx[i]][by[i]]];
 58     mp[1][s]=1;
 59     q[1].push(node(s,0));
 60     int ans=0,c,x,y;
 61     while((!q[0].empty()||!q[1].empty())&&!ans)
 62     {
 63         if(!q[0].empty())
 64         {
 65         node K=q[0].front();q[0].pop();
 66         s=K.s,c=K.c;
 67         for(int i=1;i<=8;i++)
 68         for(int j=1;j<=8;j++)
 69         {
 70             if(!(s&bin[id[i][j]])) continue;
 71             for(int k=0;k<4;k++)
 72             {
 73                 x=i+xx[k],y=j+yy[k];
 74                 fl=check(x,y,s);
 75                 if(!fl) continue;
 76                 if(fl==2){
 77                     x+=xx[k],y+=yy[k];
 78                     if(check(x,y,s)!=1) continue;
 79                 }
 80                 t=(s^bin[id[i][j]])|bin[id[x][y]];
 81                 if(mp[0].find(t)!=mp[0].end())
 82                     continue;
 83                 if(mp[1].find(t)!=mp[1].end())
 84                     {ans=1;break;}
 85                 mp[0][t]=1;
 86                 if(c<3) q[0].push(node(t,c+1));
 87                 if(ans==1) break;
 88             }
 89         }
 90         }
 91         if(!q[1].empty())
 92         {
 93         node K=q[1].front();q[1].pop();
 94         s=K.s,c=K.c;
 95         for(int i=1;i<=8;i++)
 96         for(int j=1;j<=8;j++)
 97         {
 98             if(!(s&bin[id[i][j]])) continue;
 99             for(int k=0;k<4;k++)
100             {
101                 x=i+xx[k],y=j+yy[k];
102                 fl=check(x,y,s);
103                 if(!fl) continue;
104                 if(fl==2){
105                     x+=xx[k],y+=yy[k];
106                     if(check(x,y,s)!=1) continue;
107                 }
108                 t=(s^bin[id[i][j]])|bin[id[x][y]];
109                 if(mp[1].find(t)!=mp[1].end())
110                     continue;
111                 if(mp[0].find(t)!=mp[0].end())
112                     {ans=1;break;}
113                 mp[1][t]=1;
114                 if(c<3) q[1].push(node(t,c+1));
115                 if(ans==1) break;
116             }
117         }
118         }
119     }
120     if(ans==1)
121         printf("YES\n");
122     else
123         printf("NO\n");
124     mp[0].clear();
125     mp[1].clear();
126     }
127     return 0;
128 }

原文地址:https://www.cnblogs.com/guapisolo/p/10003072.html

时间: 2024-10-13 19:16:25

poj 1198 / hdu 1401 Solitaire (记忆化搜索+meet in middle)的相关文章

POJ 2192 &amp;&amp; HDU 1501 Zipper (记忆化搜索)

Zipper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16803   Accepted: 5994 Description Given three strings, you are to determine whether the third string can be formed by combining the characters in the first two strings. The first tw

POJ 1351 Number of Locks (记忆化搜索 状态压缩)

Number of Locks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1161   Accepted: 571 Description In certain factory a kind of spring locks is manufactured. There are n slots (1 < n < 17, n is a natural number.) for each lock. The height

HDU 4597(记忆化搜索 dfs 参考)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 Problem Description Alice and Bob are playing a game. There are two piles of cards. There are N cards in each pile, and each card has a score. They take turns to pick up the top or bottom card from

POJ 3249 Test for Job (记忆化搜索 好题)

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9512   Accepted: 2178 Description Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, It's hard to have a job

hdu 1978(记忆化搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1978 How many ways Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2945    Accepted Submission(s): 1727 Problem Description 这是一个简单的生存游戏,你控制一个机器人从一

poj 1661 Help Jimmy(记忆化搜索)

题目链接:http://poj.org/problem?id=1661 一道还可以的记忆化搜索题,主要是要想到如何设dp,记忆化搜索是避免递归过程中的重复求值,所以要得到dp必须知道如何递归 由于这是个可以左右移动的所以递归过程肯定设计左右所以dp的一维为从左边下或者从右边下,而且和层数有关所以另一维为层数 于是便可以得到dp[count][flag],flag=1表示count层从左边下要多久,flag=0表示count层从右边下要多久.然后就是dfs的递归 过程 #include <iost

不要62 hdu 2089 dfs记忆化搜索

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给你两个数作为一个闭区间的端点,求出该区间中不包含数字4和62的数的个数 思路: 数位dp中的 dfs 记忆化搜索方法解. 模板: int dfs(int i, int s, bool e) { if (i==-1) return s==target_s; if (!e && f[i][s] != -1) return f[i][s]; int res = 0; int u = e?

poj 1579(动态规划初探之记忆化搜索)

Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17843   Accepted: 9112 Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <= 0 or b <= 0 or c <= 0, then w(a, b

POJ 1351-Number of Locks(记忆化搜索)

Number of Locks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1140   Accepted: 559 Description In certain factory a kind of spring locks is manufactured. There are n slots (1 < n < 17, n is a natural number.) for each lock. The height