码迷,mamicode.com
首页 > 其他好文 > 详细

HDU3567

时间:2017-09-06 10:08:06      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:lis   break   代码注释   相同   print   blog   数字   names   map   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567

解题思路:

  根据X的位置将初始状态分为9种:first[9][10]={"X12345678", "1X2345678", ......, "12345678X"}。对于每一种初始状态,根据X的位置找到对应的 first[][]。比如说,对于146X25378到2478356X1的转换,146X25378对应的就是123X45678,那么此时2代表的其实就是4,3代表的就是6,4代表的是2,6代表的是3,那么2478356X1对应的就是4278653X1,我们只要求123X45678到4278653X1的转换就可以了。

  这样一来这道题其实就跟HDU1042差不多了。我们还是用state这个结构体来表示每一种状态,用康托展开来为每一种状态找到一个对应的数。先以九个first[]为起点做9次BFS,记录下从每个firtst[]能到达的各个状态,然后正式询问的时候直接利用预处理好的信息来返回答案就好了。

  具体的几个细节看代码注释吧。

AC代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <map>
  4 using namespace std;
  5 const int maxn = 5e5;
  6 int cx[4] = { 1,0,0,-1 }, cy[4] = { 0,-1,1,0 };
  7 char go[6] = "dlru";
  8 
  9 struct state {
 10     int from;    //记录上一个状态,方便后期方向读取and
 11     int pos;    //记录X的位置
 12     char num[10];
 13     char dos;    //记录从上一步走到这一步要进行的操作
 14 };
 15 state node[9][maxn];
 16 int vis[9][maxn];    //记录对应的状态在node[][]数组中的位置
 17 char first[9][10] = { "X12345678","1X2345678","12X345678","123X45678","1234X5678","12345X678","123456X78","1234567X8","12345678X" };
 18 map<char, char> lists; //记录在此次询问中,1~8各个数字对应的数字
 19 //康托展开
 20 int factor[] = { 1,1,2,6,24,120,720,5040,40320,362880 };
 21 int cantor(char x[]) {
 22     int sum = 0, s;
 23     for (int i = 0; i<9; i++) {
 24         s = 0;
 25         for (int j = i + 1; j<9; j++) {
 26             if (x[j]<x[i])   s++;
 27         }
 28         sum += s*factor[9 - i - 1];
 29     }
 30     return sum;
 31 }
 32 void init(char now[10], int ind) {
 33     node[ind][0].from = -1, node[ind][0].pos = ind;
 34     for (int i = 0; i<9; i++)    node[ind][0].num[i] = now[i];
 35     node[ind][0].num[9] = \0;
 36     vis[ind][cantor(now)] = -1;
 37     int head = 0, ending = 1;
 38     state nows, next;
 39     while (head<ending) {    //用数组写队列
 40         nows = node[ind][head];
 41         for (int i = 0; i<4; i++) {
 42             int x = nows.pos / 3, y = nows.pos % 3;
 43             int dx = x + cx[i], dy = y + cy[i];
 44             if (dx<0 || dx>2 || dy<0 || dy>2)  continue;
 45             next.pos = dx * 3 + dy;
 46             for (int j = 0; j<9; j++) 
 47                 next.num[j] = nows.num[j];
 48             next.num[next.pos] = X;
 49             next.num[nows.pos] = nows.num[next.pos];
 50             int ct = cantor(next.num);
 51             if (!vis[ind][ct]) {
 52                 vis[ind][ct] = ending;
 53                 next.dos = go[i];
 54                 next.from = head;
 55                 node[ind][ending] = next;
 56                 ending++;
 57             }
 58         }
 59         head++;
 60     }
 61 }
 62 char ans[100];    //记录答案
 63 int find_ans(int ind, int n) {
 64     int ii = 0;
 65     for (; node[ind][n].from != -1; n = node[ind][n].from) {
 66         ans[ii++] = node[ind][n].dos;
 67     }
 68     return ii;
 69 }
 70 int main() {
 71     int T;
 72     char s[10], t[10];
 73     for (int i = 0; i<9; i++)
 74         init(first[i], i);
 75     scanf("%d", &T);
 76     for (int i = 1; i <= T; i++) {
 77         scanf("%s", s);
 78         scanf("%s", t);
 79         bool same = true;
 80         for (int j = 0; j<9; j++) {
 81             if (s[j] != t[j]) {
 82                 same = false;
 83                 break;
 84             }
 85         }
 86         if (same) {        //注意:s 和 t 一开始就相同的情况!
 87             printf("Case %d: 0\n\n", i);
 88             continue;
 89         }
 90         int ind = 0;
 91         for (; ind<9; ind++) {
 92             if (s[ind] == X) break;
 93         }
 94         for (int j = 0; j<9; j++) {
 95             if (j != ind) {
 96                 lists[s[j]] = first[ind][j];
 97             }
 98         }
 99         for (int j = 0; j<9; j++) {
100             if (t[j] != X) {
101                 t[j] = lists[t[j]];
102             }
103         }
104         int ct = cantor(t);
105         int ll = find_ans(ind, vis[ind][ct]);
106         printf("Case %d: %d\n", i, ll);
107         for (int j = ll - 1; j >= 0; j--) {
108             printf("%c", ans[j]);
109         }
110         printf("\n");
111     }
112     return 0;
113 }

 

HDU3567

标签:lis   break   代码注释   相同   print   blog   数字   names   map   

原文地址:http://www.cnblogs.com/Blogggggg/p/7482710.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!