题意

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. 一段良好的程序永远不应该发生panic异常

    panic来自被调函数的信号,表示发生了某个已知的bug.一段良好的程序永远不应该发生panic异常 对于大部分程序而言,永远无法保证能够成功运行,因为错误原因往往超出程序员的控制范围.任何进行io操 ...

  2. spring源码:web容器启动(li)

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  3. Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池

    连接池原理 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接池 ...

  4. js操作table表格导出数据到excel方法

    js导出excel资料很少,网上也找了很多,基本都不能用,要么只能是IE用,还必须要权限,这是非常不好的.后来到github上找到table2excel.js,虽然可以用,但仍然对IE支持不够,也算不 ...

  5. 仿QQ空间根据位置弹出PopupWindow显示更多操作效果

    我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图:       ...

  6. px-rem 一个将px转换为rem的工具

    将px转换为rem的工具,github地址:https://github.com/finance-sh/px-rem 怎样转换静态文件 安装: npm install px-rem -g 然后跑下命令 ...

  7. UIScrollView的封装

    UIScrollView的封装 效果 特点 1.用法简单,尺寸大小,随意设置位置 2.可以有多个数据源的数据,可以定制不通的界面(如同上图,一个有文字,一个没有文字) 3.能够实现点击事件 用法 1. ...

  8. 在Ubuntu和Linux Mint上安装Oracle JDK

    在Ubuntu和Linux Mint上安装Oracle JDK 使用下面的命令安装,只需一些时间,它就会下载许多的文件,所及你要确保你的网络环境良好: sudo add-apt-repository ...

  9. T-SQL 实现行转列

    问题: 我正在寻找一种有效的方式将行转换为SQL服务器中的列 例如,通过下表如何构建出预期结果表. Id  Value   ColumnName 1   John    FirstName 2   2 ...

  10. 使用Nexus搭建Maven本地仓库

    阅读目录 序 Nexus 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 在工作中可能存在有 ...