hdu 1226スーパーパスワード

5037 ワード

スーパーパスワード
Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3110    Accepted Submission(s): 1006
Problem Description
Ignatiusは1週間かけてやっと伝説の宝物を見つけました.宝物は1つの部屋に置かれています.部屋のドアはパスワードでロックされています.ドアのそばの壁にはパスワードに関するヒントがあります.
パスワードはC進数で、与えられたM個の数字でしか構成できないが、パスワードは与えられた10進数の整数N(0<=N<=5000)の正の整数倍(複数の条件を満たす数があれば、最小はパスワード)であり、このようなパスワードが保存されている場合は、入力するとドアが開き、このようなパスワードが存在しない場合は...ドアを爆破しましょう.
注意:宝の歴史が古いため、当時のシステムは最大500ビットのパスワードしか保存できなかった.そのため、得られたパスワードの長さが500より大きくてもドアを開けることができなかった場合、パスワードは存在しないと考えられている.
 
Input
入力データの最初の行は1つの整数T(1<=T<=300)であり、テストデータの数を表す.各テストデータの最初の行は2つの整数N(0<=N<=5000)とC(2<=C<=16)であり、ここでNはタイトル記述における所定の10進数の整数を表し、Cはパスワードの進数である.テストデータの2行目は整数M(1<=M<=16)であり、パスワードを構成する数字の数を表す.そして、パスワードを構成する数字を表すM個の数字である.2つのテストデータの間には空行が隔てられている.
注意:与えられたM個の数字の中に、10を超える数があれば、Aで10、Bで11、Cで12、Dで13、Eで14、Fで15を表すことを約束します.入力データが合法であることを保証します.
 
Output
テストデータのセット毎に要求するパスワードがある場合はそのパスワードを出力し、パスワードが存在しない場合は「give me the bomb please」を出力.
注意:パスワードを構成する数字は必ずしもすべて使わなければならないとは限らない.パスワードは非常に長い可能性があります.整数変数でパスワードを保存しようとしないでください.パスワードの最上位は0ではないことを保証します(パスワード自体が0でない限り).
 
Sample Input

   
   
   
   
3 22 10 3 7 0 1 2 10 1 1 25 16 3 A B C

 
Sample Output

   
   
   
   
110 give me the bomb please CCB
Hint
Hint
Huge input, scanf is recommended.

 
中国語の問題については、説明しません.
考え方:BFS、数字が大きすぎるので、型抜きの結果を毎回メモしてmod=0の最小値を探します
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;

int a[20];
int vis[5555];
int n,c;
int m;
char str;
string tmp;
int flag;

struct Node
{
    string ans;
    int mod;
}f,t;

queue<Node>q;

void bfs()
{
    for(int i=1;i<16;i++)
    {
        if(a[i])
        {
            int tt=i%n;
            vis[tt]=1;

            t.mod=tt;
            t.ans="";
            if(i<10) t.ans+=(i+'0');
            else t.ans+=(i-10+'A');
            q.push(t);
        }
    }

        while(!q.empty())
        {
            t=q.front();q.pop();

            if(flag && t.ans.size()>tmp.size())continue;

            if(t.mod==0)
            {
                if(flag==0) tmp=t.ans;
                flag=1;

                if( tmp.size()>t.ans.size() || (tmp.size()==t.ans.size() && tmp>t.ans) )
                    tmp=t.ans;
            }

            for(int i=0;i<16;i++)
            {
                if(a[i]==0) continue;

                if(i<10)
                {
                    f=t;
                    f.ans+=(i+'0');
                    f.mod=(f.mod*c+i)%n;
                    if( (vis[f.mod]==0 && f.ans.size()<=500) || f.mod==0 )
                    {
                        vis[f.mod]=1;
                        q.push(f);
                    }
                }
                else
                {
                    f=t;
                    f.ans+=(i-10+'A');
                    f.mod=(f.mod*c+i)%n;

                    if( (vis[f.mod]==0 && f.ans.size()<=500) || f.mod==0 )
                    {
                        vis[f.mod]=1;
                        q.push(f);
                    }

                }

            }

        }

}

int main()
{
    int T;
    while(~scanf("%d",&T))
    {
        while(T--)
        {
            scanf("%d %d",&n,&c);
            scanf("%d",&m);
            getchar();

            memset(a,0,sizeof a);
            memset(vis,0,sizeof vis);

        for(int i=0;i<m;i++)
        {
            scanf("%c",&str);
            if(str>='0' && str<='9')
                a[str-'0']=1;
            else if(str>='A' && str<='F')
                a[str-'A'+10]=1;

            getchar();
        }

        if(n==0)
        {
            if(a[0])
                printf("0
"); else puts("give me the bomb please"); continue; } while(!q.empty()) q.pop(); flag=0; bfs(); if(flag) cout<<tmp<<endl; else puts("give me the bomb please"); } } return 0; }