UESTC_魔法少女小蟹 CDOJ 710

小蟹是一名魔法少女,能熟练的施放很多魔法。

有一天魔法学院上课的时候出现了这样一道题,给一个6位数,让大家用自己的魔法,把这个6位数变成另一个给定的6位数。

小蟹翻了下魔法书,发现她有以下6种魔法:

  1. 将当前魔杖指向的数字与最左端的一个数字调换位置。
  2. 将当前魔杖指向的数字与最右端的一个数字调换位置。
  3. 将当前魔杖指向的数字+1。(若当前魔杖指向的数字为9则无效)
  4. 将当前魔杖指向的数字−1。(若当前魔杖指向的数字为0则无效)
  5. 将当前魔杖向右移动一位。
  6. 将当前魔杖向左移动一位。

最开始,她的魔杖指向的是最左边的数字。

于是小蟹很好奇,以她的能力,施展几次魔法能完成老师的这道题呢?

Input

多组数据,请处理至文件结束(EOF)

对于每组数据,包含两个6位数,a,b。

Output

对于每组数据,输出一个数,代表最少施展魔法的次数。

Sample input and output

Sample Input Sample Output
123456 654321
11

解题报告

不好想。。肯定不能处理操作3和操作4,那样bfs直接爆炸。。。本题连A*也不行。。因为状态数实在太多,又是多Case。。

难保不TLE,因此我们预处理出魔杖能到达地方的状态,之后扫一遍所有状态,加上差值就完辣

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cstdio>
  5 using namespace std;
  6
  7 const int MaxHashSize = 1526597;
  8 const int MaxStatusSize = 5000000;
  9 typedef struct status
 10 {
 11 int step,value;
 12 bool arrive[6];
 13 };
 14
 15
 16 int Head[MaxHashSize];
 17 int Next[MaxStatusSize];
 18 status st[MaxStatusSize];
 19 int caculate[7] = {1000000,100000,10000,1000,100,10,1};
 20 int tar_num[6];
 21
 22 void Hash_init()
 23 {
 24  memset(Head,-1,sizeof(Head));
 25 }
 26
 27 int GetHashNum(int& x)
 28 {
 29  return x % MaxHashSize;
 30 }
 31
 32 bool insert_Hash(int id)
 33 {
 34  int h = GetHashNum(st[id].value);
 35  int t = Head[h];
 36  while(t != -1)
 37  {
 38      if(st[id].value == st[t].value)
 39       return false;
 40     t = Next[t];
 41  }
 42  Next[id] = Head[h];
 43  Head[h] = id;
 44  return true;
 45 }
 46
 47
 48
 49 int bfs()
 50 {
 51  int front = 0,rear = 1;
 52  insert_Hash(0);
 53  while(front < rear)
 54   {
 55       status ss = st[front++];
 56       int num[7];
 57       int ori = ss.value;
 58       for(int i = 6 ; i >=0 ; --i)
 59         {
 60           num[i] = ss.value % 10;
 61         ss.value /= 10;
 62        }
 63     int pos = num[6];
 64     bool flag = true;
 65     if (num[pos] == 0 || pos == 0) flag = false;
 66     if (flag)
 67      {
 68         st[rear] = ss;
 69          int temp = num[0];
 70          num[0] = num[pos];
 71          num[pos] = temp;
 72          int value = 0;
 73          for(int i = 0 ; i < 7 ; ++ i)
 74           value += (num[i]*caculate[i]);
 75            st[rear].value = value;
 76            if (insert_Hash(rear))
 77               {
 78                   st[rear].step = ss.step + 1;
 79                   st[rear++].arrive[0] = true;
 80               }
 81              num[pos] = num[0];
 82              num[0] = temp;
 83      }
 84    flag = true;
 85    if (num[5]  == 0 && pos == 0) flag = false;
 86    if (pos == 5) flag = false;
 87    if (flag)
 88     {
 89           st[rear] = ss;
 90        int temp  = num[5];
 91        num[5] = num[pos];
 92        num[pos] = temp;
 93        int value = 0;
 94        for(int i = 0 ; i < 7 ; ++ i)
 95           value += (num[i]*caculate[i]);
 96            st[rear].value = value;
 97            if (insert_Hash(rear))
 98               {
 99                  st[rear].step = ss.step + 1;
100                  st[rear++].arrive[5] = true;
101              }
102           num[pos] = num[5];
103              num[5] = temp;
104     }
105    if (pos < 5)
106     {
107         st[rear] = ss;
108         int value = ori + 1;
109         st[rear].value = value;
110         if (insert_Hash(rear))
111          {
112              st[rear].step = ss.step + 1;
113             st[rear++].arrive[pos+1] = true;
114           }
115     }
116    if (pos > 0)
117     {
118         st[rear] = ss;
119         int value = ori - 1;
120         st[rear].value = value;
121         if (insert_Hash(rear))
122          {
123              st[rear].step = ss.step + 1;
124              st[rear++].arrive[pos-1] = true;
125           }
126     }
127   }
128  return rear;
129 }
130
131
132 int slove(int x)
133 {
134  int Mo = 999;
135  for(int i = 0 ; i < x; ++ i)
136   {
137       //cout << "i is " << i << endl;
138       int num[6];
139       st[i].value /= 10;
140       int ori = st[i].value;
141       for(int j = 5;j >=0 ;--j)
142         {
143           num[j] = st[i].value % 10;
144           st[i].value /= 10;
145        }
146     int res = st[i].step;
147     for(int k = 0 ; k < 6;++k)
148      if (tar_num[k] != num[k] && !st[i].arrive[k])
149       {
150           res = 999;
151           break;
152       }
153      else
154      res += (abs(tar_num[k]-num[k]));
155     //cout << "Res is " << res << endl;
156     Mo = min(Mo,res);
157   }
158 return Mo;
159 }
160
161
162 int main(int argc, char * argv[])
163 {
164  int s1,s2;
165  while(scanf("%d%d",&s1,&s2) == 2)
166   {
167       Hash_init();
168       st[0].value = s1*10;
169       st[0].step = 0;
170       memset(st[0].arrive,false,sizeof(st[0].arrive));
171       st[0].arrive[0] = true;
172       for(int i = 5;i>=0;--i)
173         {
174            tar_num[i] = s2 % 10;
175            s2 /= 10;
176        }
177       cout << slove(bfs()) << endl;
178   }
179  return 0;
180 }
时间: 2024-10-06 05:14:04

UESTC_魔法少女小蟹 CDOJ 710的相关文章

UESTC_贪吃蛇 CDOJ 709

相信大家都玩过贪吃蛇游戏吧. 在n×m的迷宫中,有着一条长度不超过9的贪吃蛇,它已经将所有的食物吃光了,现在的目标是移动到出口. 它走的时候不能碰到自己的身体,也不能碰到墙壁.(如果贪吃蛇的长度>3并且下一步要走到自己的尾部,是合法的) 问它能不能走到出口,如果能,最少要移动几步? Input 数据包含多组数据,请读入到文件末尾EOF 每组数据第一行包含两个整数n,m(1≤n,m≤15)代表迷宫的大小. 接下来n行,每行包含一个长度为m的字符串,来表示迷宫. 字符串中仅包含..#.@.1 ~ 9

UESTC_温泉旅店 CDOJ 878

天空飘下一朵一朵的雪花,这是一片纯白的世界. 在天空之下的温泉旅店里,雪菜已醉倒在一旁,冬马与春希看了看说着梦话的雪菜,决定找一点玩的来度过这愉快的晚上. 这家旅店提供一种特色游戏,游戏有n张牌,各写有一个数字,数字可能相同也可能不同,冬马和春希都可以从中拿出任意张(也可以不拿,被其中一个人拿过的牌,另一个人肯定是拿不了了.),各自的得分为他们手中牌上的数字的异或和. 春希身为一个男孩子,觉得自己理应让下女孩子,决定只有自己的得分大于冬马的时候才算自己赢,不过多管闲事的他还是想知道有多少种拿法,

UESTC_摩天轮 CDOJ 879

一天,冬马被春希和雪菜拉着去一起去游乐园玩. 经过了各种过山车的洗礼后,三人决定去坐摩天轮休息下. 这是一个巨大的摩天轮,每一个车厢能坐任意多的人.现在,等着坐摩天轮的有n个人(包含他们3人),摩天轮还有m个车厢可以坐人.每个人都有自己肥胖程度,出于某些原因,胖子和瘦子坐在同一节车厢就会产生一定的矛盾,这个矛盾的值为(MAX−MIN)2,其中MAX为当前车厢里面最胖的人的肥胖程度,MIN为最廋的那个人的肥胖程度. 爱管闲事的春希当然不希望就因为这点小事而使大家的这趟旅途不愉快,于是他决定帮大家安

UESTC 魔法少女小蟹

转自http://www.cnblogs.com/whatbeg/p/3728557.html 直接BFS肯定不行,复杂度太高. 先不考虑加加减操作,因为它们不涉及以为,很好处理. 因为一开始魔棒是在最左端,所以第i个位置被访问过了,则前面的一定都访问过.同时,我们可以直接通过和最后一位交换的方式访问最后一位.所以所有被访问的状态(标号)就只有1.12.123.1234.12345.123456.16.126.1236.12346,就10个. 所以状态记录就是dis[6][6][6][6][6]

UESTC_方老师的分身 II CDOJ 915

方老师的分身 II Time Limit: 10000/5000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方老师计算出了走路时间最长的那个分身所用的时间.于是有个特殊的分身(据说是方老师真身!)就不想如此古板的走最短路了!由于这个分身的特殊性,这个分身对于单向边可以当双向边走.但是这个特殊的分身想走最短路的同时,要求至少经过k条边. Input 有多组数据 第一行两个整数n,m(1≤n

UESTC_敢说就敢做 CDOJ 631

敢说就敢做 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status beap总是自诩敢说又敢做,又到了情人节,为了体现自己的勇气可嘉,beap决定给自己喜欢的女生买玫瑰花,以此表达自己的爱意.到花店里,他发现一共有K种花,同时他从网上得知,送N朵花的花语是LOVE,所以他决定在所有的花里面选N朵出来送给心爱的女生,但是又为了显示自己买了那么多种花,他决定这K

UESTC_握手 CDOJ 913

握手 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 一群人参加了一次聚会,其中有一些人是好朋友.一对朋友见面后握手且仅握一次手,并且每个人不会和自己握手(废话!).现在告诉你每个人一共握了几次手,请你判断是否存在一种朋友关系满足每个人的握手数. Input 输入多组数据,第一行一个数T,表述数据组数.每组数据第一行输入一个数n,表示有n个人参加了聚

UESTC_我要长高 CDOJ 594

韩父有N个儿子,分别是韩一,韩二…韩N.由于韩家演技功底深厚,加上他们间的密切配合,演出获得了巨大成功,票房甚至高达2000万.舟子是名很有威望的公知,可是他表面上两袖清风实则内心阴暗,看到韩家红红火火,嫉妒心遂起,便发微薄调侃韩二们站成一列时身高参差不齐.由于舟子的影响力,随口一句便会造成韩家的巨大损失,具体亏损是这样计算的,韩一,韩二…韩N站成一排,损失即为C×(韩i与韩i+1的高度差(1≤i<N))之和,搞不好连女儿都赔了.韩父苦苦思索,决定给韩子们内增高(注意韩子们变矮是不科学的只能增高

UESTC_棋盘游戏 CDOJ 578

最近昀昀学习到了一种新的棋盘游戏,这是一个在一个N×N的格子棋盘上去搞M个棋子的游戏,游戏的规则有下列几条: 棋盘上有且仅有一个出口 开始时没有哪个棋子在出口,而且所有棋子都不相邻(这里的相邻是指上下左右四个方向) M个棋子分别记为1到M 每个时刻你可以移动一个棋子向它相邻的四个格子移动一步 你需要保证任意时刻棋盘上所有棋子都不相邻 只有当前棋盘上编号最小的棋子移动到出口时才能取走改棋子. 所有棋子都移走的时候游戏结束 对于一个给定的游戏局面,昀昀最少要多少步才能结束这个游戏呢? Input 第