[Vijos1898]学姐吃生鱼片 解题报告

这道题思路挺简洁的,但却绝对足够让我耳目一新了。

一、题意

描述

学姐今晚想吃生鱼片, doc便领着她去吃啦. 但是怎么能这样轻易就让馋嘴的学姐吃到生鱼片呢!

于是doc准备了一个"二维魔方".
所谓 二维魔方, 可以被考虑为平面上 3X3 的方格, 里面不重复得填有 1~9 共9个数字.
每一次可以对某一行或某一列向某一方向做轮换操作, 比如说, 如果第三列原来的数字依次为 3 6 9, 那么针对第三列向上轮换一次后 就变成了: 6 9 3; 再向上轮换一次后 就变成了9 3 6.
现在doc给出了 二维魔方的初始状态, 再给出目标状态. 初始状态是由1~9组成的 3X3 的数字方格, 而目标状态中某个位置被标记为星号, 表示可以是任意数字.
如果学姐能用最少的操作次数得到目标状态, doc就会喂她吃一小块生鱼片呢!

格式

输入格式

第一行一个整数T, 表示总的询问次数.
之后有T次询问, 对于每一次询问, 有6行, 每行3组字符(包括数字1~9和星号)以空格隔开.

输出格式

对于每一次询问, 输出一行.
首先输出询问的标号(参见样例输出), 之后输出最少的操作次数. 如果不可能做到, 输出"No Solution!"(不输出引号).

样例1

样例输入1[复制]

2
1 2 3
4 5 6
7 8 9
8 * 9
5 3 7
2 * *
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 9 8 

样例输出1[复制]

Case #1: 7
Case #2: No Solution!

限制

对于30%的数据, T <= 3
对于60%的数据, T <= 100
对于100%的数据, T <= 1000

二、题解

看到它我起初完全没有思路,只能暴搜,然后看了看题解,题解就一句话:一遍预处理BFS。

什么玩意儿!完全看不懂,啥叫一遍预处理?咋预处理啊?它初始状态和目标状态全不一样啊!

然后我问了ljs学长,终于搞明白了。。

学长说:虽然这么多初始状态,但是它们本质上都是一样的!


原来虽然这么多初始状态是不一样的,但是我们可以都将其映射到某一特定排列,例如123456789,然后令目标状态以同样的方式映射即可。这样的话,就把多源最短路优化成了单源最短路 !


做到这里,不仅想到约瑟夫问题和地精部落,同样是1~N的排列,同样的思想,同样的神奇!

①排列是可以离散的!在以后的学习中,处理排列问题时我想我必须牢牢记住这一点;在排列问题中,离散排列总是具有化腐朽为神奇的力量。

三、BFS中的代码技巧

1、用循环和函数来代替繁杂的拓展过程;

2、用交换来代替题意中蛋疼的旋转魔方。

3、②千万不要忘记回溯!随时思考变量的意义!

4、③如果写代码过程中突然想到了某些优化或更改,最好把它写下来;否则很可能改了这边忘了那边,导致程序出现差错。

5、④不要忘了编制数据和对拍。数据和代码一样重要!

#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
char * ptr=(char *)malloc(100000);
inline void in(int &x){
<span style="white-space:pre">	</span>while(*ptr<'0'||*ptr>'9')++ptr;
<span style="white-space:pre">	</span>x=0;
<span style="white-space:pre">	</span>while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
}
#define J9 362880
int q[J9][9]={1,2,3,4,5,6,7,8,9},ni[]={1,1,2,6,24,120,720,5040,40320},dis[J9],ans[J9],h,t,Ans;
bool p[J9],tmp[10];
int kangtuo(int a[]){
<span style="white-space:pre">	</span>bool p[10];
<span style="white-space:pre">	</span>int sum,ans=0,i,j;
<span style="white-space:pre">	</span>memset(p,1,sizeof(p));
<span style="white-space:pre">	</span>for(i=0;i<9;++i){
<span style="white-space:pre">		</span>sum=0;
<span style="white-space:pre">		</span>for(j=1;j<a[i];++j)
<span style="white-space:pre">			</span>sum+=p[j];
<span style="white-space:pre">		</span>ans+=sum*ni[8-i];
<span style="white-space:pre">		</span>p[a[i]]=0;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return ans;
}
inline void add(int a[]){
<span style="white-space:pre">	</span>int kt=kangtuo(a);
<span style="white-space:pre">	</span>if(p[kt])return;
<span style="white-space:pre">	</span>p[kt]=1;
<span style="white-space:pre">	</span>memcpy(q[t],a,9*sizeof(int));
<span style="white-space:pre">	</span>dis[t]=dis[h]+1;
<span style="white-space:pre">	</span>ans[kt]=dis[t++];
}
inline void build(int x){
<span style="white-space:pre">	</span>if(x==9){
<span style="white-space:pre">		</span>Ans=min(Ans,ans[kangtuo(q[0])]);
<span style="white-space:pre">		</span>return;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>if(q[0][x]+1)build(x+1);
<span style="white-space:pre">	</span>else{
<span style="white-space:pre">		</span>for(int i=1;i<10;++i)
<span style="white-space:pre">			</span>if(!tmp[i]){
<span style="white-space:pre">				</span>q[0][x]=i;
<span style="white-space:pre">				</span>tmp[i]=1;
<span style="white-space:pre">				</span>build(x+1);
<span style="white-space:pre">				</span>tmp[i]=0;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>q[0][x]=-1;
<span style="white-space:pre">	</span>}
}
inline void inchr(int &x){
<span style="white-space:pre">	</span>while((*ptr<'0'||*ptr>'9')&&*ptr!='*')++ptr;
<span style="white-space:pre">	</span>x=*ptr=='*'?-1:*ptr-'0';
<span style="white-space:pre">	</span>++ptr;
}
int main(){
<span style="white-space:pre">	</span>int i,kt,X,T;
<span style="white-space:pre">	</span>/*------Prework-----*/
<span style="white-space:pre">	</span>memset(ans,127,sizeof(ans));
<span style="white-space:pre">	</span>t=1;
<span style="white-space:pre">	</span>kt=kangtuo(q[0]);
<span style="white-space:pre">	</span>p[kt]=1;
<span style="white-space:pre">	</span>ans[kt]=0;
<span style="white-space:pre">	</span>for(h=0;h!=t;++h){
<span style="white-space:pre">		</span>/*--Change in row---*/
<span style="white-space:pre">		</span>for(i=3,X=1;i--;X+=3){
<span style="white-space:pre">			</span>swap(q[h][X-1],q[h][X+1]);
<span style="white-space:pre">			</span>/*---Direction I--*/
<span style="white-space:pre">			</span>swap(q[h][X-1],q[h][X]);
<span style="white-space:pre">			</span>add(q[h]);
<span style="white-space:pre">			</span>swap(q[h][X-1],q[h][X]);
<span style="white-space:pre">			</span>/*---Direction II--*/
<span style="white-space:pre">			</span>swap(q[h][X],q[h][X+1]);
<span style="white-space:pre">			</span>add(q[h]);
<span style="white-space:pre">			</span>swap(q[h][X],q[h][X+1]);
<span style="white-space:pre">			</span>
<span style="white-space:pre">			</span>swap(q[h][X-1],q[h][X+1]);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>/*--Change in line---*/
<span style="white-space:pre">		</span>for(i=3,X=3;i--;++X){
<span style="white-space:pre">			</span>swap(q[h][X-3],q[h][X+3]);
<span style="white-space:pre">			</span>/*---Direction I--*/
<span style="white-space:pre">			</span>swap(q[h][X-3],q[h][X]);
<span style="white-space:pre">			</span>add(q[h]);
<span style="white-space:pre">			</span>swap(q[h][X-3],q[h][X]);
<span style="white-space:pre">			</span>/*---Direction II--*/
<span style="white-space:pre">			</span>swap(q[h][X],q[h][X+3]);
<span style="white-space:pre">			</span>add(q[h]);
<span style="white-space:pre">			</span>swap(q[h][X],q[h][X+3]);
<span style="white-space:pre">			</span>
<span style="white-space:pre">			</span>swap(q[h][X-3],q[h][X+3]);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>/*--Read and Work Out--*/
<span style="white-space:pre">	</span>fread(ptr,1,100000,stdin);
<span style="white-space:pre">	</span>in(T);
<span style="white-space:pre">	</span>int point[10];
<span style="white-space:pre">	</span>bool flag;
<span style="white-space:pre">	</span>for(int k=1;k<=T;++k){
<span style="white-space:pre">		</span>memset(tmp,0,sizeof(tmp));
<span style="white-space:pre">		</span>for(i=1;i<10;++i){
<span style="white-space:pre">			</span>inchr(X);
<span style="white-space:pre">			</span>point[X]=i;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>flag=1;
<span style="white-space:pre">		</span>for(i=0;i<9;++i,++ptr){
<span style="white-space:pre">			</span>inchr(q[0][i]);
<span style="white-space:pre">			</span>if(q[0][i]+1){
<span style="white-space:pre">				</span>flag=0;
<span style="white-space:pre">				</span>q[0][i]=point[q[0][i]];
<span style="white-space:pre">				</span>tmp[q[0][i]]=1;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if(flag){
<span style="white-space:pre">			</span>printf("Case #%d: 0\n",k);
<span style="white-space:pre">			</span>continue;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>Ans=0x7fffffff;
<span style="white-space:pre">		</span>build(0);
<span style="white-space:pre">		</span>printf("Case #%d: ",k);
<span style="white-space:pre">		</span>if(Ans<100000000)printf("%d",Ans);
<span style="white-space:pre">		</span>else printf("No Solution!");
<span style="white-space:pre">		</span>printf("\n");
<span style="white-space:pre">	</span>}
}


你可能感兴趣的:(hash,bfs)