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,要不然就是神奇模拟,也没有复杂算法!!
经常犯错的地方无非就是初始化、重置、清零之类的地方,检查的时候要注意。