题意

4*2个格子分别为

1234

8765

的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格。

现在给出目标状态,找出最少步数可从原始状态到达目标状态,且输出最小字典序的操作序列。

题解

bfs,全排列编码判重可以用康托展开,也可以用vis[8][8][8][8][8][8][8]来判重,因为第八位是固定的,所以要开\(8^7\)的空间。

代码

/*
USER:19flipp1
TASK:msquare
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define in(s) freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);
#define N 10
using namespace std;
int a[N],fac[N];
struct node{
int a[N];
int d;
char s[25];
}nd;
bool vis[320000];
int cantor(int a[N]){
int ans=0,c;
for(int i=1;i<8;i++){
c=0;
for(int j=i;j<=8;j++)if(a[i]>a[j])c++;
ans+=fac[8-i]*c;
}
return ans;
}
void work(int a[],int i){
if(i==0){
for(int j=1;j<=4;j++)swap(a[j],a[9-j]);
}else if(i==1){
int t=a[1];
a[1]=a[4],a[4]=a[3],a[3]=a[2],a[2]=t;
t=a[5];
a[5]=a[6],a[6]=a[7],a[7]=a[8],a[8]=t;
}else if(i==2){
int t=a[2];
a[2]=a[7];a[7]=a[6];a[6]=a[3];a[3]=t;
}
}
void bfs(){
queue<node> q;
node p;
for(int i=1;i<=8;i++)p.a[i]=i;
p.d=0;
q.push(p);
while(!q.empty()){
node p=q.front();
q.pop();
int ok=1;
for(int i=1;i<=8;i++)if(p.a[i]!=nd.a[i]){ok=0;break;}
if(ok){
printf("%d\n",p.d);
for(int i=1;i<=p.d;i++)
printf("%c",p.s[i]);
puts("");
break;
}
for(int i=0;i<3;i++){
node np=p;
work(np.a,i);
int num=cantor(np.a);
if(!vis[num]){
vis[num]=1;
np.d++;
np.s[np.d]='A'+i;
q.push(np);
}
}
}
}
int main(){
in(msquare);
fac[0]=1;
for(int i=1;i<=8;i++){
scanf("%d",&nd.a[i]);
fac[i]=fac[i-1]*i;
}
bfs();
return 0;
}

代码2

/*
USER:19flipp1
TASK:msquare
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define in(s) freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);
#define N 10
using namespace std;
int a[N],fac[N];
struct node{
int a[N];
int d;
char s[25];
}nd;
bool vis[8][8][8][8][8][8][8];
void work(int a[],int i){
if(i==0){
for(int j=1;j<=4;j++)swap(a[j],a[9-j]);
}else if(i==1){
int t=a[1];
a[1]=a[4],a[4]=a[3],a[3]=a[2],a[2]=t;
t=a[5];
a[5]=a[6],a[6]=a[7],a[7]=a[8],a[8]=t;
}else if(i==2){
int t=a[2];
a[2]=a[7];a[7]=a[6];a[6]=a[3];a[3]=t;
}
}
bool Vis(int a[]){
bool &t=vis[a[1]-1][a[2]-1][a[3]-1][a[4]-1][a[5]-1][a[6]-1][a[7]-1];
if(t)return 1;
t=1;
return 0;
}
void bfs(){
queue<node> q;
node p;
for(int i=1;i<=8;i++)p.a[i]=i;
p.d=0;
q.push(p);
while(!q.empty()){
node p=q.front();
q.pop();
int ok=1;
for(int i=1;i<=8;i++)if(p.a[i]!=nd.a[i]){ok=0;break;}
if(ok){
printf("%d\n",p.d);
for(int i=1;i<=p.d;i++)
printf("%c",p.s[i]);
puts("");
break;
}
for(int i=0;i<3;i++){
node np=p;
work(np.a,i);
if(!Vis(np.a)){
np.d++;
np.s[np.d]='A'+i;
q.push(np);
}
}
}
}
int main(){
in(msquare);
fac[0]=1;
for(int i=1;i<=8;i++){
scanf("%d",&nd.a[i]);
fac[i]=fac[i-1]*i;
}
bfs();
return 0;
}

【USACO 3.2】Magic Squares的更多相关文章

  1. 【USACO 1.2】Palindromic Squares

    进制转换,然后判断是否是回文 /******************************************* TASK: palsquare LANG: C++ Created Time: ...

  2. 【Usaco 2009 Gold】JZOJ2020年9月19日提高B组T4 过路费

    [Usaco 2009 Gold]JZOJ2020年9月19日提高B组T4 过路费 题目 Description 跟所有人一样,农夫约翰以着宁教我负天下牛,休叫天下牛负我的伟大精神,日日夜夜苦思生财之 ...

  3. 【Usaco 2009 Gold】JZOJ2020年9月19日提高B组T3 头晕的奶牛

    [Usaco 2009 Gold]JZOJ2020年9月19日提高B组T3 头晕的奶牛 题目 Description 奶牛们发现,在农场里面赛跑是很有趣的一件事.可是她们一旦在农场里面不断地转圈,就会 ...

  4. 【Usaco 2009 Gold 】JZOJ2020年9月19日提高B组T2 电视游戏问题

    [Usaco 2009 Gold ]JZOJ2020年9月19日提高B组T2 电视游戏问题 题目 Description 农夫约翰的奶牛们游戏成瘾!本来FJ是想要按照陶叫兽的做法拿她们去电击戒瘾的,可 ...

  5. 【Usaco 2009 Silver】JZOJ2020年9月19日提高B组T1 音乐节拍

    [Usaco 2009 Silver]JZOJ2020年9月19日提高B组T1 音乐节拍 题目 Description FJ准备教他的奶牛弹奏一首歌曲,歌曲由N(1<=N<=50,000) ...

  6. 【USACO 2012 Open】Running Laps(树状数组)

    53 奶牛赛跑 约翰有 N 头奶牛,他为这些奶牛准备了一个周长为 C 的环形跑牛场.所有奶牛从起点同时起跑,奶牛在比赛中总是以匀速前进的,第 i 头牛的速度为 Vi.只要有一头奶牛跑完 L 圈之后,比 ...

  7. 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉

    DP/单调队列优化 首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $  当然这里的$i$和$k$都是偶数啦~ ...

  8. 【USACO 3.1】Stamps (完全背包)

    题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...

  9. 【USACO 3.1】Contact(01子串按出现次数排序)

    题意:给你一个01字符串,将长度为a到b之间(包含a.b)的子串按照出现次数排序.注意输入输出格式 题解:01子串对应一个二进制,为了区别11和011这样的不同子串,我们把长度也记录下来,官方题解是在 ...

随机推荐

  1. 浅谈Collection集合

    俗话说:一个东西,一件事都离不开三句话:"是什么,为什么,怎么办" 集合是什么: 集合简单的说一个数组集合的高级体现,用来存储数据或对象的容器: 集合为什么存在: 集合只是体现了对 ...

  2. SAP CRM 通过调试观察CL_CRM_BOL_ENTITY中的数据

    这个(BOL里面)最重要的类值得一看. BOL中的每条记录都会在CL_CRM_BOL_ENTIT中表示.至今,我们已经写过一些事件处理器,并且我们已经直接或间接的通过这个类工作.在业务场景中,我们也许 ...

  3. Andriod 自定义控件之音频条

    今天我们实现一个直接继承于View的全新控件.大家都知道音乐播放器吧,在点击一首歌进行播放时,通常会有一块区域用于显示音频条,我们今天就来学习下,播放器音频条的实现. 首先我们还是先定义一个类,直接继 ...

  4. 安卓DJ113舞曲网应用客户端 项目源码(服务器+客户端)

    Android DJ113舞曲网app客户端 播放器源码  项目源码(服务器+客户端),这个项目整体有点类似天天动听的效果,非常漂亮的,支持第三方登录等功能,非常完整的一个音乐项目. 源码下载:htt ...

  5. web移动端开发技巧与注意事项汇总

    一.meta的使用 1.<meta name="viewport" content="width=device-width,initial-scale=1.0, m ...

  6. MYSQL基础操作之数据约束与关联查询

    一.MYSQL约束 1.默认值约束,当字段没有插入值的时候,mysql自动给该字段分配默认值. 默认值的字段允许为空. 对默认值字段也可以插入null. CREATE TABLE STUDENT( I ...

  7. SecondaryNameNode的工作流程

    SecondaryNameNode是用来合并fsimage和edits文件来更新NameNode和metadata的. 其工作流程为: 1.secondary通知namenode切换edits文件 2 ...

  8. protobuf的编译安装

    github地址:https://github.com/google/protobuf支持多种语言,有多个语言的版本,本文采用的是在centos7下编译源码进行安装. github上有详细的安装说明: ...

  9. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  10. hadoop常用的操作命令

    1.显示hdfs上test目录下的所有文件列表 hadoop fs -ls /test/ 2.查看hdfs中的文件内容 hadoop fs -cat /daas/bstl/term/rawdt/201 ...