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][6][6][10],前6个6 代表现在的第i位是原来的第j位,第7个6 代表魔杖现在在哪,10 代表有哪些位置被访问过了。

dis表示到当前状态的步数(最小)。

BFS出来后,枚举6位数的每一位和指针位置和10种状态,看此状态是否已访问,如果已访问,表示能够到达这个状态,然后看从这个状态到目标状态还需多少步(有可能达不到),然后看dis[状态]+步数是否小于最小步数,是则更新答案。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <queue>
  7 #define Mod 1000000007
  8 #define INT 2147483647
  9 using namespace std;
 10 #define N 50007
 11
 12 struct node
 13 {
 14     int p[7];
 15     int point,state;
 16     int step;
 17 }S;
 18
 19 void Popy(int *p1,int *p2)
 20 {
 21     for(int i=1;i<7;i++)
 22         p1[i] = p2[i];
 23 }
 24
 25 int dis[7][7][7][7][7][7][7][10];
 26 int E[7],SS[7];
 27
 28 int min(int ka,int kb)
 29 {
 30     if(ka < kb)
 31         return ka;
 32     return kb;
 33 }
 34
 35 int max(int ka,int kb)
 36 {
 37     if(ka > kb)
 38         return ka;
 39     return kb;
 40 }
 41
 42 void BFS(node S)
 43 {
 44     queue<node> que;
 45     memset(dis,-1,sizeof(dis));
 46     que.push(S);
 47     dis[S.p[1]][S.p[2]][S.p[3]][S.p[4]][S.p[5]][S.p[6]][1][0] = 0;
 48     while(!que.empty())
 49     {
 50         node tmp = que.front();
 51         que.pop();
 52         for(int i=0;i<4;i++)
 53         {
 54             node now;
 55             if(i == 0)   //与左边交换
 56             {
 57                 swap(tmp.p[1],tmp.p[tmp.point]);
 58                 Popy(now.p,tmp.p);
 59                 swap(tmp.p[1],tmp.p[tmp.point]);
 60                 now.point = tmp.point;
 61                 now.state = tmp.state;
 62                 now.step = tmp.step + 1;
 63                 if(dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] == -1 || (dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] != -1 && now.step < dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state]))
 64                 {
 65                     dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] = now.step;
 66                     que.push(now);
 67                 }
 68             }
 69             else if(i == 1)   //与右边交换
 70             {
 71                 swap(tmp.p[6],tmp.p[tmp.point]);
 72                 Popy(now.p,tmp.p);
 73                 swap(tmp.p[6],tmp.p[tmp.point]);
 74                 now.point = tmp.point;
 75                 if(tmp.state <= 3)
 76                     now.state = tmp.state + 6;
 77                 else if(tmp.state == 4)
 78                     now.state = tmp.state + 1;
 79                 else
 80                     now.state = tmp.state;
 81                 now.step = tmp.step + 1;
 82                 if(dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] == -1 || (dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] != -1 && now.step < dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state]))
 83                 {
 84                     dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] = now.step;
 85                     que.push(now);
 86                 }
 87             }
 88             else if(i == 2)   //左移
 89             {
 90                 Popy(now.p,tmp.p);
 91                 now.point = max(1,tmp.point-1);
 92                 now.state = tmp.state;
 93                 now.step = tmp.step + 1;
 94                 if(dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] == -1 || (dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] != -1 && now.step < dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state]))
 95                 {
 96                     dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] = now.step;
 97                     que.push(now);
 98                 }
 99             }
100             else if(i == 3)  //右移
101             {
102                 Popy(now.p,tmp.p);
103                 now.point = min(6,tmp.point+1);
104                 if(tmp.state < 5)
105                     now.state = tmp.state+1;
106                 else if(tmp.state == 5)
107                     now.state = tmp.state;
108                 else if(tmp.state < 9)
109                     now.state = tmp.state+1;
110                 else
111                     now.state = tmp.state-4;
112                 now.step = tmp.step + 1;
113                 if(dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] == -1 || (dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] != -1 && now.step < dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state]))
114                 {
115                     dis[now.p[1]][now.p[2]][now.p[3]][now.p[4]][now.p[5]][now.p[6]][now.point][now.state] = now.step;
116                     que.push(now);
117                 }
118             }
119         }
120     }
121 }
122
123 int main()
124 {
125     int a,b,i;
126     int h[7];
127     int pot,status;
128     while(scanf("%d%d",&a,&b)!=EOF)
129     {
130         S.p[1] = 1;   //标号。初始都在自己的位置
131         S.p[2] = 2;
132         S.p[3] = 3;
133         S.p[4] = 4;
134         S.p[5] = 5;
135         S.p[6] = 6;
136         S.point = 1;
137         S.state = 0;
138         S.step = 0;
139         SS[1] = (a/100000)%10;
140         SS[2] = (a/10000)%10;
141         SS[3] = (a/1000)%10;
142         SS[4] = (a/100)%10;
143         SS[5] = (a/10)%10;
144         SS[6] = a%10;
145         E[1] = (b/100000)%10;
146         E[2] = (b/10000)%10;
147         E[3] = (b/1000)%10;
148         E[4] = (b/100)%10;
149         E[5] = (b/10)%10;
150         E[6] = b%10;
151         BFS(S);
152         int ans = Mod;
153         for(h[1]=1;h[1]<=6;h[1]++)
154         {
155             for(h[2]=1;h[2]<=6;h[2]++)
156             {
157                 if(h[2] != h[1])
158                 {
159                     for(h[3]=1;h[3]<=6;h[3]++)
160                     {
161                         if(h[3] != h[2] && h[3] != h[1])
162                         {
163                             for(h[4]=1;h[4]<=6;h[4]++)
164                             {
165                                 if(h[4] != h[1] && h[4] != h[2] && h[4] != h[3])
166                                 {
167                                     for(h[5]=1;h[5]<=6;h[5]++)
168                                     {
169                                         if(h[5] != h[1] && h[5] != h[2] && h[5] != h[3] && h[5] != h[4])
170                                         {
171                                             for(h[6]=1;h[6]<=6;h[6]++)
172                                             {
173                                                 if(h[6] != h[1] && h[6] != h[2] && h[6] != h[3] && h[6] != h[4] && h[6] != h[5])
174                                                 {
175                                                     for(pot=1;pot<=6;pot++)
176                                                     {
177                                                         for(status=0;status<10;status++)
178                                                         {
179                                                             if(dis[h[1]][h[2]][h[3]][h[4]][h[5]][h[6]][pot][status] != -1)
180                                                             {
181                                                                 int cnt = 0;
182                                                                 int t,r;
183                                                                 int flag = 1;                      //No.  status
184                                                                 if(status <= 5)                    //1    1
185                                                                 {                                  //2    12
186                                                                     for(t=1;t<=status+1;t++)       //3    123
187                                                                         cnt += abs(E[t]-SS[h[t]]); //4    1234
188                                                                     for(t;t<=6;t++)                //5    12345
189                                                                         if(E[t] != SS[h[t]])       //6    123456
190                                                                         {                          //7    16
191                                                                             flag = 0;              //8    126
192                                                                             break;                 //9    1236
193                                                                         }                          //10   12346
194                                                                     if(!flag)
195                                                                         continue;
196                                                                 }
197                                                                 else if(status >= 6 && status <= 9)
198                                                                 {
199                                                                     for(r=1;r<=status-5;r++)
200                                                                         cnt += abs(E[r]-SS[h[r]]);
201                                                                     for(r;r<6;r++)
202                                                                         if(E[r] != SS[h[r]])
203                                                                         {
204                                                                             flag = 0;
205                                                                             break;
206                                                                         }
207                                                                     if(!flag)
208                                                                         continue;
209                                                                     cnt += abs(E[6]-SS[h[6]]);
210                                                                 }
211                                                                 ans = min(ans,dis[h[1]][h[2]][h[3]][h[4]][h[5]][h[6]][pot][status]+cnt);
212                                                             }
213                                                         }
214                                                     }
215                                                 }
216                                             }
217                                         }
218                                     }
219                                 }
220                             }
221                         }
222                     }
223                 }
224             }
225         }
226         printf("%d\n",ans);
227     }
228     return 0;
229 }
时间: 2024-10-02 04:40:44

UESTC 魔法少女小蟹的相关文章

UESTC_魔法少女小蟹 CDOJ 710

小蟹是一名魔法少女,能熟练的施放很多魔法. 有一天魔法学院上课的时候出现了这样一道题,给一个6位数,让大家用自己的魔法,把这个6位数变成另一个给定的6位数. 小蟹翻了下魔法书,发现她有以下6种魔法: 将当前魔杖指向的数字与最左端的一个数字调换位置. 将当前魔杖指向的数字与最右端的一个数字调换位置. 将当前魔杖指向的数字+1.(若当前魔杖指向的数字为9则无效) 将当前魔杖指向的数字−1.(若当前魔杖指向的数字为0则无效) 将当前魔杖向右移动一位. 将当前魔杖向左移动一位. 最开始,她的魔杖指向的是

2014 UESTC Training for Data Structures J - 方师傅的01串

J - 方师傅的01串 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方师傅过生日啦,于是蟹毛买了N个01串,想送给方师傅. 但是蟹毛觉得这些01串不够美,于是他想从中选出一些送给方师傅. 蟹毛对于p个01串的美值定义为: 这些01串的最长公共前缀的长度×p 所以蟹毛想从N个01串中选出一些,使得这些01串的美值最高. 请告诉蟹毛最好的美值是多少.

UESTC 电子科大专题训练 数据结构 D

UESTC 1584 题意:平面坐标上有n个怪物,每个怪物有一个rank值,代表x坐标和y坐标都不大于它本身的怪物数(不包括本身) 思路:对x y坐标从小到大排序,x优先排序,用数状数组计算y坐标小于它的数量 AC代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #i

UESTC 31 饭卡(Card) --背包问题

背包问题. 思路:如果m<5,此时也不能消费,所以此时答案为m m>=5: 求出背包容量为m-5,买前n-1样便宜的菜(排个序)的最大价值(即最大消费,即消费完后剩余值最接近5)最后减去最大的那个菜的价格,就得到最小的余额. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using n

UESTC 电子科大专题训练 数据结构 A

UESTC 1591 题意:求区间极值之差 思路:线段树裸题,不带更新 ACA代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "ma

2017 UESTC Training for Data Structures

2017 UESTC Training for Data Structures A    水,找区间极差,RMQ怼上去. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i&

UESTC - 878 温泉旅店 二维费用背包问题

http://acm.uestc.edu.cn/#/problem/show/878 设dp[i][j][k]表示在前i个数中,第一个得到的异或值是j,第二个人得到的异或值是k的方案数有多少种. 因为异或后的大小不确定,所以不能压缩数组,但是也不大..可以过. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm>

ACM:UESTC - 649 括号配对问题 - stack

  UESTC - 649  括号配对问题 Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: %lld & %llu Description 大家都知道算术表达式中,括号必须配对,现在任意给出一个算术表达式,判断其括号是否配对.如果配对,输出Yes,否则输出No. Input 含多组测试数据,输入首先是一个整数T表示测试数据组数(0<T≤300).随后有T行测试数据,长度不超过1000个字符,字符串间不含空格. Out

2015 CCPC D- Pick The Sticks(UESTC 1218) (01背包变形)

http://acm.uestc.edu.cn/#/problem/show/1218 既然二维dp表示不了,就加一维表示是否在边界放置,放置一个,两个.有一个trick就是如果只放一根,那么多长都可以. wa了好多次(囧) 开始因为l[i]/2会出现小数,没注意,把所有的长度都x2就可以解决. 又wa了n次因为没注意j-l[i]时没加判断,为什么不是RE呢!不开心... /********************************************* Memory: 1140 KB