zoukankan      html  css  js  c++  java
  • 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,要不然就是神奇模拟,也没有复杂算法!!

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

  • 相关阅读:
    [转]Spring Cloud在国内中小型公司能用起来吗?
    [转]关于maven pom.xml中dependency type 为pom的应用
    如何直接在github网站上更新你fork的repo?
    Eclipse在Tomcat环境下运行项目出现NoClassDefFoundError/ClassNotFoundException解决办法
    Jquery mobile 中在列表项上使用单选按钮
    QBus 关注并推送实时公交信息
    常用序列号
    SVN 使用锁实现独占式签出
    SQL速记
    利用交通在手数据为换乘添加关注
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/13160894.html
Copyright © 2011-2022 走看看