没看过题的童鞋请去看一下题-->P2730 魔板 Magic Squares

不了解康托展开的请来这里-->我这里

至于这题为什么可以用康托展开?(瞎说时间到.

因为只有8个数字,且只有1~8这8个数字,所以我们可以算出最多情况有8!=40320个.

所以我们完全可以开数组记录这些状态并且记录这些答案.

康托展开的作用就是把这些排列映射成一个排名.

如果我们存储排列,那极限情况应该是87654321,很容易就炸掉的.

而映射成排名的话,我们开的极限只有40320,大约是1/2173的空间.

因此我们就可以这样去存储状态.

  1. vis[i]代表排名为i的排列存在
  2. to[i]代表从初状态到达排名为i的状态的操作序列.//要开成string类型.

求解:

那么如何求解呢?

对于初状态{1,2,3,4,5,6,7,8}是不变的,因此我们可以用bfs预处理出来其他状态.

而要满足字典序最小,我们可以先尝试进行A操作,B操作,C操作即可。其他操作就和普通的bfs差不多了。

对操作之后的序列,我们去求一下他的排名,那我们就可以得到 变成他的操作序列.把操作序列存储进to[]数组即可。

ps:字符串string类型支持拼接操作

而我们不要忘记把序列还原

即改变一个序列有三种操作,我们不能连续进行A,B,C操作,需要对当前的序列操作.

因此就预处理出来了。

解决:

然后我们如何输入?(这里卡了好久的QwQ

getchar()可以读一切字符(应该是

所以我们就可以每次放一个getchar()!

而去一位一位的存储读入的字符串。

所以说我们就可以完美的解决这个题啦!

部分代码参考-->@qiqi_starsky

-------------------代码---------------------

  1. #include<bits/stdc++.h>
  2. #define IL inline
  3. #define RI register int
  4. using namespace std;
  5. const int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//阶乘
  6. struct code
  7. {
  8. string st,step;
  9. }s,ss;
  10. string to[666666];
  11. bool vis[666666];
  12. IL int Contor(string &s)//这里本应该不加&就可以正确的.
  13. //但不加会Wa
  14. //应该是你谷评测机的锅.
  15. //已经尝试过在bzoj提交,不加&是可以过的
  16. {
  17. int ans=0;
  18. for(RI i=0;i<8;i++)
  19. {
  20. //std::cout<<ans<<std::endl;
  21. int smaller=0;
  22. for(RI j= i+1 ;j<8;j++)
  23. {
  24. if(s[i] > s[j])smaller++;
  25. }
  26. ans += smaller*fac[8-i-1];
  27. }
  28. return ans+1;
  29. }
  30. IL void A(string &s)
  31. {
  32. for(RI i=0;i<4;i++)
  33. swap(s[i],s[8-i-1]);
  34. }
  35. IL void B(string &s)
  36. {
  37. int t=s[3];
  38. for(RI i=3;i>=1;i--)
  39. s[i]=s[i-1];
  40. s[0]=t;
  41. int tt=s[4];
  42. for(RI i=4;i<=6;i++)
  43. s[i]=s[i+1];
  44. s[7]=tt;
  45. }
  46. IL void C(string &s)
  47. {
  48. int t=s[6];
  49. s[6]=s[5];
  50. s[5]=s[2];
  51. s[2]=s[1];
  52. s[1]=t;
  53. }
  54. /*
  55. 1 2 3 4
  56. 5 6 7 8
  57. ↓ ↓ ↓ ↓
  58. 1 7 2 4
  59. 8 6 3 5
  60. */
  61. IL void bfs()
  62. {
  63. std::queue<code>q;
  64. s.st="12345678";
  65. s.step="";
  66. q.push(s);
  67. vis[Contor(s.st)]=true;
  68. while(!q.empty())
  69. {
  70. s=q.front();q.pop();
  71. ss=s;
  72. A(ss.st);//A操作
  73. int cnt=Contor(ss.st);//对于改变的操作序列求出他的排名
  74. if(!vis[cnt])
  75. {
  76. ss.step+="A";
  77. to[cnt]=ss.step;//字符串可以直接整个赋过去
  78. q.push(ss);//把一个新的字符串放过去,接下来扩展
  79. vis[cnt]=true;//标记
  80. }
  81. ss=s;//还原的操作!!!很重要!
  82. B(ss.st);//B操作
  83. cnt=Contor(ss.st);
  84. if(!vis[cnt])
  85. {
  86. ss.step+="B";
  87. to[cnt]=ss.step;
  88. q.push(ss);
  89. vis[cnt]=true;
  90. }
  91. ss=s;
  92. C(ss.st);//C操作
  93. cnt=Contor(ss.st);
  94. if(!vis[cnt])
  95. {
  96. ss.step+="C";
  97. to[cnt]=ss.step;
  98. q.push(ss);
  99. vis[cnt]=true;
  100. }
  101. }
  102. }
  103. int main()
  104. {
  105. bfs();
  106. string str;
  107. cin>>str[0];getchar();cin>>str[1];getchar();
  108. cin>>str[2];getchar();cin>>str[3];getchar();
  109. cin>>str[4];getchar();cin>>str[5];getchar();
  110. cin>>str[6];getchar();cin>>str[7];getchar();
  111. //这输入厉害不厉害!
  112. int cnt=Contor(str);
  113. cout<<to[cnt].length()<<endl;//字符串用.length()
  114. cout<<to[cnt]<<endl;
  115. }

后话

如果给定的初始序列不是{1,2,3,4,5,6,7,8}怎么办?

把初始序列看成{1,2,3,4,5,6,7,8}即可

Upd

2018.09.03

回来填坑

当我们的初始序列不是{1,2,3,4,5,6,7,8}该怎么做?

  1. 例如: 瞎出的例子emmmm
  2. 初始状态:65783241——>12345678
  3. 对应位置得到这种状态↓
  4. 终止状态:13486572——>85741236

更详细一点↓

看好如何对应。

  1. 初状态 6 5 7 8 3 2 4 1

  2. 对应为 1 2 3 4 5 6 7 8
  3. 即我们要把想得到的状态
  4. 1 3 4 8 6 5 7 2
  5. 用上面的对应关系转化

过程↓

  1. 1 发现 1->8
  2. 3 发现 3->5
  3. 4 发现 4->7
  4. 8 发现 8->4
  5. 6 发现 6->1
  6. 5 发现 5->2
  7. 7 发现 7->3
  8. 2 发现 2->6
  9. 最终得到8 5 7 4 1 2 3 6

如果不理解,请仔细再看一下。

这样我们求解{6,5,7,8,3,2,4,1}到{1,3,4,8,6,5,7,2}的操作,

就转变为了{1,2,3,4,5,6,7,8}到{8,5,7,4,1,2,3,6}的操作.

代码实现转化↓(尝试理解一下,懒得码字了 emmm

  1. for (int i=0; i<8 ; i++)
  2. num[s[i]-'0']=i+1;
  3. //看看我们的枚举,所以需要i+1得到1,2,3.....8
  4. //get关系↑.s存储初状态
  5. //转化关系↓.str存储末状态
  6. for (int i=0; i<8 ; i++)
  7. str[i]=num[str[i]-'0']+'0';

如果有新的知识,我还会来Upd的

(逃

Upd:

2018.09.05

关于康托展开那里的字符串是否需要加&不知道是否会有疑问?

感谢@cellur925

的提问

已经在bzoj尝试不加&,是可以AC的.

并通过在我谷下载数据并尝试debug,发现输出是一样的.

Contor函数并没有涉及到修改原串,因此不加&应该是正确的.

感觉应该是你谷评测机的锅

而其他A,B,C操作是需要修改原串的,需要加&.

PS:加&是可以引用变量的.

哈希+Bfs【P2730】 魔板 Magic Squares的更多相关文章

  1. 洛谷 P2730 魔板 Magic Squares 解题报告

    P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...

  2. 洛谷 P2730 魔板 Magic Squares

    P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...

  3. [洛谷P2730] 魔板 Magic Squares

    洛谷题目链接:魔板 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都 ...

  4. P2730 魔板 Magic Squares

    题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...

  5. 洛谷 - P2730 - 魔板 Magic Squares - bfs

    写状态转移弄了很久,老了,不记得自己的数组是怎么标号的了. #include <bits/stdc++.h> using namespace std; #define ll long lo ...

  6. P2730 魔板 Magic Squares (搜索)

    题目链接 Solution 这道题,我是用 \(map\) 做的. 具体实现,我们用一个 \(string\) 类型表示任意一种情况. 可以知道,排列最多只有 \(8!\) 个. 然后就是直接的广搜了 ...

  7. 【简●解】 LG P2730 【魔板 Magic Squares】

    LG P2730 [魔板 Magic Squares] [题目背景] 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 ...

  8. [USACO3.2]魔板 Magic Squares

    松下问童子,言师采药去. 只在此山中,云深不知处.--贾岛 题目:魔板 Magic Squares 网址:https://www.luogu.com.cn/problem/P2730 这是一张有8个大 ...

  9. 「一本通 1.4 例 2」[USACO3.2]魔板 Magic Squares

    [USACO3.2]魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题 ...

随机推荐

  1. [hdu 4348]区间修改区间查询可持久化线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348 一开始把lazy标记给push_down了,后来发现这样会让持久化变乱,然后想到不用push_d ...

  2. POJ1456:Supermarket(并查集+贪心)

    Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17634   Accepted: 7920 题目链接 ...

  3. php getimagesize()函数获取图片宽度高度

    //php自带函数 getimagesize() $img_info = getimagesize('tomener.jpg'); echo '<pre>'; print_r($img_i ...

  4. Python爬虫学习笔记之爬取新浪微博

    import requests from urllib.parse import urlencode from pyquery import PyQuery as pq from pymongo im ...

  5. css实现九宫格图片自适应布局

    我之前写九宫格自适应布局的时候,每个格子是使用媒体查询器(@media)或者js动态设置css,根据不同的手机屏幕宽度,适配不同手机,但是这样有个很大的缺点,那就是移动端的屏幕尺寸太多了,就得写很多代 ...

  6. DecimalFormat中格式化问题

    一:前言 每天自己斗会看到新的东西,每天自己都会学到东西,但是觉得自己老是想一口吃一个胖子.每天看到一个知识点都把其收藏了,但是自己也没有时间去看,不知道自己到底想感谢什么.真是自己无语,本来说是把自 ...

  7. Spring 学习笔记(三)之注解

    一.在classpath下扫描组件 •组件扫描(component scanning):  Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件. •特定组件包括: ...

  8. UITableView学习之辨析两个方法:⓵dequeueReusableCellWithIdentifier与⓶dequeueReusableCellWithIdentifier:forIndexPath:

    使用storyboard显示UITableView时,如果不修改系统默认生成的tableView:cellForRowAtIndexPath:方法中的代码,必须为UITableViewCell注册(填 ...

  9. HDU1003MAX SUM (动态规划求最大子序列的和)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  10. HDU 2554 N对数的排列问题 ( 数学 )

    题目链接 Problem Description 有N对双胞胎,他们的年龄分别是1,2,3,--,N岁,他们手拉手排成一队到野外去玩,要经过一根独木桥,为了安全起见,要求年龄大的和年龄小的排在一起,好 ...