12F:数字变换

总时间限制: 
1000ms
 
内存限制: 
65536kB
描述

给定一个包含5个数字(0-9)的字符串,例如 “02943”,请将“12345”变换到它。 你可以采取3种操作进行变换

1. 交换相邻的两个数字

2. 将一个数字加1。如果加1后大于9,则变为0

3. 将一个数字加倍。如果加倍后大于9,则将其变为加倍后的结果除以10的余数。

最多只能用第2种操作3次,第3种操作2次 求最少经过多少次操作可以完成变换。

输入
有最多 100,000 组数据
每组数据就是包含5个数字的字符串
输出
对每组数据,输出将"12345"变换到给定字符串所需要的最少操作步数。如果无法变换成功,输出-1
样例输入
12435
99999
12374
样例输出
1
-1
3
提示
由于测试数据太多,如果对每组数据都从头进行搜索,就会超时。

建议先做预处理,即以“12345”作为初始状态做一遍彻底的广搜,找出“12345”经合法变换能够到达的所有字符串,并记录到达这些字符串各需要多少步操作。

然后对读入的每组数据,在上述预处理记录的结果中进行查询即可。
来源
Guo Wei
 1 #include<iostream>
 2 #include<string>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<queue>
 6 using namespace std;
 7 char a[6] = "12345";
 8 bool vis[100000][4][3];
 9 int ans[100000];
10 struct node{
11     string a;
12     int op2, op3, step;
13     node(string aa, int o2, int o3, int ss = 0):a(aa),op2(o2),op3(o3), step(ss){};
14 };
15 queue<node>q;
16 int main(){
17     memset(vis, false, sizeof(vis));
18     memset(ans, -1, sizeof(ans));
19     q.push(node("12345",0,0));
20     vis[12345][0][0] = true;
21     ans[12345] = 0;
22     while(!q.empty()){
23         node no = q.front();
24         q.pop();
25         string temp = no.a;
26         if(ans[int(atof(temp.c_str()))]==-1)ans[int(atof(temp.c_str()))] = no.step;
27     //    cout<<no.a<<endl;
28         //第一种操作 
29         for(int i = 0; i < 4; i++){
30             swap(temp[i], temp[i+1]);
31             if(!vis[int(atof(temp.c_str()))][no.op2][no.op3]){
32                 vis[int(atof(temp.c_str()))][no.op2][no.op3] = true;
33                 q.push(node(temp, no.op2, no.op3, no.step+1));
34             }
35             swap(temp[i], temp[i+1]);
36         }
37         //第二种操作 
38         if(no.op2<3){
39             for(int i = 0; i < 5; i++){
40                 temp = no.a;
41                 int num = temp[i] - '0';
42                 num++; 
43                 if(num==10) num = 0;
44                 temp[i] = '0'+num;
45                 if(!vis[int(atof(temp.c_str()))][no.op2+1][no.op3]){
46                     vis[int(atof(temp.c_str()))][no.op2+1][no.op3] = true;
47                     q.push(node(temp, no.op2+1, no.op3, no.step+1));
48                 }
49             }
50         } 
51 
52         //第三种操作 
53         if(no.op3<2){
54             for(int i = 0; i < 5; i++){
55                 temp = no.a;
56                 int num = temp[i] - '0';
57                 num*=2; 
58                 if(num>9) num %= 10;
59                 temp[i] = '0'+num;
60                 if(!vis[int(atof(temp.c_str()))][no.op2][no.op3+1]){
61                     vis[int(atof(temp.c_str()))][no.op2][no.op3+1] = true;
62                     q.push(node(temp, no.op2, no.op3+1, no.step+1));
63                 }
64             }
65         }
66     }
67     while(cin>>a){
68         cout<<ans[int(atof(a))]<<endl;
69     }
70     return 0; 
71 }

备注:睡前能用两次就过了这道题很开心!!!WA是因为vis数组初始化成了-1 orz 之前还犯过的错误是,temp没有及时在每个循环的开头重置成a。

最开始思考了一下,用什么来定义状态,记录已经进行了哪些操作吗?好像没法记……然后想到,每个数最大就99999,可以把数字定义为状态啊。另外,因为操作二和操作三都有次数限制,所以这个次数也要纳入维度里,所以就用一个三维vis数组来记录状态就可以了。

这道题获得的启发就是,不要怂,搜就行了,反正一共就考那么几种算法,不是动规就是考BFS就是DFS,要不然就是神奇模拟,也没有复杂算法!!

经常犯错的地方无非就是初始化、重置、清零之类的地方,检查的时候要注意。

posted @ 2020-06-19 00:11  timeaftertime  阅读(623)  评论(0编辑  收藏  举报