一类数位限制倍数的BFS问题...URAL 1495,POJ 1465,HDU 4474,HDU 1226

56 篇文章 0 订阅

            这类问题是给定了能出现哪些数字或者不能出现哪些数字...然后问一个数的最少多少倍可以满足条件...

            这个是昨天模拟去年杭州现场赛时碰到的...我以为不会有太多位(猜测50)..然后用数位DP来推...结果WA出翔..主要是位数可能会相当长..看后来的其他题目500+都可能的..数位DP绝对跪....

            正解是BFS+Hash...Hash指的是对于每个数字作为最后一个数字..能得到哪些余数..hash[10][MOD]..这样就能看出其实总的状态是有限的...并且不多..为了找到答案..那么从第一位开始BFS直到出来解就行...


Ural - 1495

题意:

       给出一个数...问起最小的倍数得到的数让其只含1和2...没有或者长度大于30位..则输出Impossible.

Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 1000005
#define esp 1e-30
using namespace std;    
struct node
{
       int x,s,L;
};
int pre[3][MAXN][2];
queue<node> Q;
void dfs(int x,int s)
{
       if (x==-1) return;
       dfs(pre[x][s][0],pre[x][s][1]);
       printf("%d",x);
}
void BFS(int MOD)
{
       int t;
       node h,k; 
       memset(pre,-0x7f,sizeof(pre));
       while (!Q.empty()) Q.pop();
       for (t=1;t<3;t++)
             h.x=t,h.s=t%MOD,h.L=1,Q.push(h),pre[h.x][h.s][0]=-1;
       while (!Q.empty())
       {
              h=Q.front(),Q.pop();
              if (h.L>30) break;
              if (!h.s)
              {
                      dfs(h.x,h.s);
                      printf("\n");
                      return;
              }
              for (t=1;t<3;t++) 
              {
                      k.x=t,k.s=(h.s*10+t)%MOD,k.L=h.L+1;
                      if (pre[k.x][k.s][0]>=-1) continue;
                      pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
                      Q.push(k);
              }
       }            
       puts("Impossible");
} 
int main()
{     
       int n; 
       scanf("%d",&n),BFS(n);
       return 0;
}

POJ 1465,HDU 4474

题意:

       这两题是差不多的意思(POJ1465是给出哪些数字能用..HDOJ是给出哪些数字不能用)...意思是限制了能用哪些数字..现在给出一个数N..问其最小的倍数得到的数仅有能用的数字组成

Program(POJ 1465):

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 5505
#define esp 1e-30
using namespace std;    
struct node
{
       int x,s;
};
bool f[10];
int pre[10][MAXN][2];
queue<node> Q;
void dfs(int x,int s)
{
       if (x==-1) return;
       dfs(pre[x][s][0],pre[x][s][1]);
       printf("%d",x);
}
void BFS(int MOD)
{
       int t;
       node h,k;
       if (!MOD)
       {
              puts("0");
              return;
       }
       memset(pre,-0x7f,sizeof(pre));
       while (!Q.empty()) Q.pop();
       for (t=1;t<10;t++)
          if (f[t]) 
             h.x=t,h.s=t%MOD,Q.push(h),pre[h.x][h.s][0]=-1;
       while (!Q.empty())
       {
              h=Q.front(),Q.pop();
              if (!h.s)
              {
                      dfs(h.x,h.s);
                      printf("\n");
                      return;
              }
              for (t=0;t<10;t++)
                 if (f[t])
                 {
                      k.x=t,k.s=(h.s*10+t)%MOD;
                      if (pre[k.x][k.s][0]>=-1) continue;
                      pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
                      Q.push(k);
                 }
       }            
       puts("0");
} 
int main()
{     
       int n,m,x;  
       while (~scanf("%d%d",&n,&m))
       {
                memset(f,false,sizeof(f));
                while (m--)  scanf("%d",&x),f[x]=true;
                BFS(n);
       }
       return 0;
}

Program(HDU 4474):

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include <stack>
#include<queue>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define MAXN 100005
#define ll long long
#define pi acos(-1.0) 
using namespace std;   
struct node
{
      int x,s,pre; 
};
bool f[10],hash[10][10005]; 
int pre[10][100005][2];
queue<node> Q;
void dfs(int x,int s)
{
      if (x==-1) return;
      dfs(pre[x][s][0],pre[x][s][1]);
      printf("%d",x);
}
void BFS(int MOD)
{
      int i;
      node h,k;
      memset(hash,false,sizeof(hash));
      while (!Q.empty()) Q.pop();
      memset(pre,-1,sizeof(pre));
      for (i=1;i<10;i++) 
         if (f[i]) 
           h.x=i,hash[i][h.s=i%MOD]=true,Q.push(h);
      while (!Q.empty())
      {
               h=Q.front(),Q.pop();    
               if (!h.s)
               { 
                        dfs(h.x,h.s); 
                        puts("");
                        return;
               }  
               for (i=0;i<10;i++)
                  if (f[i])
                  { 
                        k.x=i,k.s=(h.s*10+i)%MOD;
                        if (hash[k.x][k.s]) continue; 
                        hash[k.x][k.s]=true;
                        pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
                        Q.push(k);
                  }
      } 
      puts("-1");
}
int main()
{        
      int cases=0,x,n,num; 
      while (~scanf("%d%d",&n,&num))
      { 
              memset(f,true,sizeof(f));
              while (num--) scanf("%d",&x),f[x]=false;   
              printf("Case %d: ",++cases); 
              BFS(n);   
      }
      return 0;
}

HDU 1226

题意:

      给了一个十进制数N,给了一个进制(2~16)..并且给出在这个进制下能用的数字(>=10的用A,B,C,D,E,F标记)..问N最少多少倍得到的数是有所给的字符组成的...

题解:

      不管几个进制都是一回事...

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 5505
#define esp 1e-30
using namespace std;    
struct node
{
       int x,s,L;
};
bool f[16];
int pre[16][MAXN][2];
queue<node> Q;
void DFS(int x,int s)
{
       if (x==-1) return;
       DFS(pre[x][s][0],pre[x][s][1]); 
       if (x<10) printf("%d",x);
            else printf("%c",x-10+'A');
}
void BFS(int C,int MOD)
{
       if (!MOD)
       {
                if (f[0]) puts("0");
                     else puts("give me the bomb please");
                return;
       } 
       int i,x,t;
       node h,k;
       memset(pre,-0x2f,sizeof(pre)); 
       while (!Q.empty()) Q.pop();
       for (i=1;i<C;i++)
         if (f[i])
           h.x=i,h.s=i%MOD,h.L=1,Q.push(h),pre[h.x][h.s][0]=-1;
       while (!Q.empty())
       {
                h=Q.front(),Q.pop();
                if (h.L>500) break;
                if (!h.s)
                {
                        DFS(h.x,h.s);
                        puts("");
                        return;
                } 
                for (i=0;i<C;i++)
                   if (f[i])
                   {
                           k.x=i,k.s=(h.s*C+i)%MOD,k.L=h.L+1;
                           if (pre[k.x][k.s][0]>=-1) continue;
                           pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
                           Q.push(k);
                   }
       }
       puts("give me the bomb please");
}
int main()
{    
       int cases,N,C,M,x;
       char c; 
       scanf("%d",&cases);
       while (cases--)
       {
                scanf("%d%d%d",&N,&C,&M);
                memset(f,false,sizeof(f)); 
                while (M--)
                {
                       do { c=getchar(); } while (c==' ' || c=='\n');
                       if (c>='0' && c<='9')
                       { 
                               x=0;
                               while (c>='0' && c<='9')
                               {
                                      x=x*10+c-'0';
                                      c=getchar();
                               }
                       }else
                               x=10+c-'A';
                       f[x]=true;
                }   
                BFS(C,N);
       }
       return 0;
}




    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值