• HDU3567


    题目链接: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] = '';
     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
    
    ", 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
    ", i, ll);
    107         for (int j = ll - 1; j >= 0; j--) {
    108             printf("%c", ans[j]);
    109         }
    110         printf("
    ");
    111     }
    112     return 0;
    113 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    js-AOP
    jQueryUI之autocomplete
    nginx安装配置
    oracle结构语法
    ajax/表单提交 多个相同name的处理方法
    ES6模块化
    docker运维
    帆软报表
    oracle锁表
    香港到大陆IPLC节点故障
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7482710.html
Copyright © 2020-2023  润新知