• hdu1226超级密码 bfs


    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1226/

    题目大意是:寻找一个五百位之内的C进制密码,该密码是N的正整数倍,而且只能用给定的数构成密码,求这样的密码最小是多少。思路也不难想到,密码的位数有限,我们可以通过广度优先搜索来搜索目标状态,通过已经拼接好的密码再在最后添加一位就能产生扩展后的密码,也就是层数增加一层,我们可以一层层搜索,但是五百层是绝对不可能通过不剪枝的方法就能搜完的。剪枝的条件是:对于余数相同的数,只让最小的数入队。

    证明如下:

    假设a=k1*n+q(0<=q<n),b=k2*n+q(0<=q<n),而且 k2>k1,(即a,b余数相同但是a大)那么再进行扩展时,t*a+c=(t*k1)*n+t*q+c,t*b=(t*k2)*n+t*q+c,此时必有t*a>t*b,而且两者模n的余数一定是相等的,如果余数都是0,那么显然t*b+c更加小,所以对于每一种余数,我们只要保存最小数的进行扩展就能保证最终第一个出现的N倍数的数是最小的密码。若选择较大的数成功搜索,则比它小的余数相同的数按照同样的步骤肯定能成为N的倍数。

    代码如下:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef unsigned int ui;
      4 typedef long long ll;
      5 typedef unsigned long long ull;
      6 #define pf printf
      7 #define mem(a,b) memset(a,b,sizeof(a))
      8 #define prime1 1e9+7
      9 #define prime2 1e9+9
     10 #define pi 3.14159265
     11 #define lson l,mid,rt<<1
     12 #define rson mid+1,r,rt<<1|1
     13 #define scand(x) scanf("%llf",&x) 
     14 #define f(i,a,b) for(int i=a;i<=b;i++)
     15 #define scan(a) scanf("%d",&a)
     16 #define dbg(args) cout<<#args<<":"<<args<<endl;
     17 #define inf 0x3f3f3f3f
     18 #define maxn 510
     19 #define maxm 5010
     20 int n,m,t,c;
     21 int book[20];
     22 bool vis[maxm];
     23 struct node{
     24     int a[maxn];
     25     int len;//分别保存每一位密码,密码长度
     26 };
     27 int getmod(node tmp)//获取余数的函数 
     28 {
     29     int ans=0;
     30     f(i,0,tmp.len-1)
     31     {
     32         ans=(ans*c+tmp.a[i])%n; 
     33         //应用多项式的计算,由于加法和乘法对于模运算的顺序是不影响的 
     34      } 
     35      return ans;
     36  } 
     37  node cur,ans;
     38  bool flag=false;
     39  void print(node tmp)
     40  {
     41      f(i,0,tmp.len-1)
     42      {
     43          if(tmp.a[i]<10)pf("%d",tmp.a[i]);
     44          else pf("%c",tmp.a[i]-10+'A');
     45      }
     46      putchar('
    ');
     47  }
     48 
     49 void bfs()
     50 {
     51      queue<node>q;
     52     node st;
     53     st.len=0;
     54     int r;
     55     f(i,1,15)//首位特判,因为不能为零 
     56     {
     57         if(book[i])
     58         {
     59             st.len=1;
     60             st.a[0]=i;
     61              r=getmod(st);
     62                 if(!r)
     63                 {
     64                     flag=1;
     65                     ans=st;
     66                     return;
     67                 }
     68                 if(!vis[r])
     69                 {
     70                     q.push(st);
     71                     vis[r]=1;
     72                 }
     73         }
     74     }
     75         while(!q.empty())
     76         {
     77             cur=q.front();
     78             q.pop();
     79             f(i,0,15)
     80             {
     81                 if(book[i])
     82                 {
     83                     cur.len++;
     84                     cur.a[cur.len-1]=i;
     85                     r=getmod(cur);
     86                     if(!r)
     87                     {
     88                         flag=1;
     89                         ans=cur;
     90                         return;
     91                     }
     92                     if(!vis[r]&&cur.len<500)
     93                     {
     94                         vis[r]=1;
     95                         q.push(cur);
     96                     }
     97                     cur.len--;
     98                 }
     99             }
    100         }
    101 }
    102 int main()
    103 {
    104     //freopen("input.txt","r",stdin);
    105     //freopen("output.txt","w",stdout);
    106     std::ios::sync_with_stdio(false);
    107     scan(t);
    108     while(t--)
    109     {
    110         mem(book,0);
    111         mem(vis,false);
    112         flag=false;
    113         scan(n);scan(c);
    114         scan(m);
    115         getchar();
    116         char x[3];
    117         while(m--)
    118         {
    119             scanf("%s",x);
    120             if(x[0]>='0'&&x[0]<='9')book[x[0]-'0']=1;//保存可访问的数 
    121             else book[x[0]-'A'+10]=1;
    122         }
    123         if(n==0)
    124         {
    125             if(book[0])//如果要求密码是0的倍数,那么密码就是0,要是给了0就完成,没给0不可以达成目的
    126             pf("0
    ");
    127             else pf("give me the bomb please
    "); 
    128         }
    129         else 
    130         {
    131             bfs();
    132             if(flag)
    133             {
    134                 print(ans);
    135             }
    136             else pf("give me the bomb please
    ");
    137         }
    138     }
    139     return 0;    
    140  } 
  • 相关阅读:
    Java进阶(七)布隆过滤器
    NIO面试题
    TCP/IP面试题
    SPRING面试题
    SpringBoot(五)原理剖析:Transaction原理
    SpringBoot(四)原理剖析:AOP原理
    SpringBoot(三)原理剖析:IOC原理
    SpringBoot(二)原理剖析:AutoConfiguration原理
    mysql 安全更新
    查看端口占用
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12513446.html
Copyright © 2020-2023  润新知