搜索专题题解(下)

还有四个题……

E:hdu1015

Safecracker

Problem Description
=== Op tech briefing, 2002/11/02 06:42 CST === 
"The item is locked in a Klein safe behind a painting in the second-floor library. Klein safes are extremely rare; most of them, along with Klein and his factory, were destroyed in World War II. Fortunately old Brumbaugh from research knew Klein's secrets and wrote them down before he died. A Klein safe has two distinguishing features: a combination lock that uses letters instead of numbers, and an engraved quotation on the door. A Klein quotation always contains between five and twelve distinct uppercase letters, usually at the beginning of sentences, and mentions one or more numbers. Five of the uppercase letters form the combination that opens the safe. By combining the digits from all the numbers in the appropriate way you get a numeric target. (The details of constructing the target number are classified.) To find the combination you must select five letters v, w, x, y, and z that satisfy the following equation, where each letter is replaced by its ordinal position in the alphabet (A=1, B=2, ..., Z=26). The combination is then vwxyz. If there is more than one solution then the combination is the one that is lexicographically greatest, i.e., the one that would appear last in a dictionary." 

v - w^2 + x^3 - y^4 + z^5 = target 

"For example, given target 1 and letter set ABCDEFGHIJKL, one possible solution is FIECB, since 6 - 9^2 + 5^3 - 3^4 + 2^5 = 1. There are actually several solutions in this case, and the combination turns out to be LKEBA. Klein thought it was safe to encode the combination within the engraving, because it could take months of effort to try all the possibilities even if you knew the secret. But of course computers didn't exist then." 

=== Op tech directive, computer division, 2002/11/02 12:30 CST === 

"Develop a program to find Klein combinations in preparation for field deployment. Use standard test methodology as per departmental regulations. Input consists of one or more lines containing a positive integer target less than twelve million, a space, then at least five and at most twelve distinct uppercase letters. The last line will contain a target of zero and the letters END; this signals the end of the input. For each line output the Klein combination, break ties with lexicographic order, or 'no solution' if there is no correct combination. Use the exact format shown below."
 

Sample Input
   
   
   
   
1 ABCDEFGHIJKL 11700519 ZAYEXIWOVU 3072997 SOUGHT 1234567 THEQUICKFROG 0 END
 

Sample Output
   
   
   
   
LKEBA YOXUZ GHOST no solution
直接搜就好,其实写个五重循环也可达到目的
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
long n,m;
long a[42];
long re[42];
bool v[42];
bool flag;
string s;
long last[42];
int cmp(int a,int b)
{
    return a>b;
}
long mi(long a,long t)
{
    long tmp=1;
    for (long i=1;i<=t;i++)
        tmp=tmp*a;
    if ((t%2)==0) return(-tmp);
    return(tmp);
}

long dfs(long dep)
{
    if(dep>=6)
    {
        long tmp=0;
        for (long i=1;i<=5;i++)
        {
            tmp=tmp+mi(re[i],i);
        }
        if(tmp==n) return true;

        return false;
    }
    for(long i=0;i<m;i++)
    {
        if(!v[a[i]])
        {
            re[dep]=a[i];
            v[a[i]]=true;
            //cout<<dep<<' '<<a[i]<<endl;
            if(dfs(dep+1)) return true;
            v[a[i]]=false;
        }
    }
    return 0;
}

int main()
{
   // freopen("E.in","r",stdin);
    //freopen("E.out","w",stdout);
    cin>>n>>s;
    while ((n!=0)||(s!="END"))
    {
        flag=false;
        memset(a,0,sizeof(a));
        memset(v,0,sizeof(v));
        m=0;
        for (long i=0;i<s.size();i++)
        {
            a[i]=s[i]-'A'+1;;
        }
        m=s.size();
        sort(a,a+m,cmp);
        if(dfs(1))
        {
            for(long i=1;i<=5;i++)
            {
                printf("%c",re[i]+'A'-1);
            }
            printf("\n");
        }
        else
        {
            printf("no solution\n");
        }

        cin>>n>>s;
    }
    return 0;

}


F:hdu1016

Prime Ring Problem

Problem Description

A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.

Note: the number of first circle should always be 1.

搜索专题题解(下)_第1张图片
 


Input

n (0 < n < 20).
 

Output

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.

You are to write a program that completes above process.

Print a blank line after each case.
 

Sample Input

   
   
   
   
6 8
 

Sample Output

   
   
   
   
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 2: 1 2 3 8 5 6 7 4 1 2 5 8 3 4 7 6 1 4 7 6 5 8 3 2 1 6 7 4 3 8 5 2

裸搜啊!注意要判定最后一个和1相加的结果,输方案的时候注意格式,pe真的挺不划算啊……

#include<iostream>
#include<cstring>
#include<cstdio>
#include<math.h>
#include<stdlib.h>
using namespace std;

int flag;
long n,m,t;
long sx,sy,tx,ty;
bool a[42];
bool su[42];
long last[42];
void susu()
{
    memset(su,1,sizeof(su));
    su[1]=false;
    for (long i=2;i<=40;i++)
    {
        for (long t=2;i*t<=40;t++)
        {
            su[t*i]=false;
        }
    }
  //  for (long i=2;i<=40;i++)
   //     cout<<i<<' '<<su[i]<<endl;
}

void print_solution(long x)
{
    if (x==1)
    {

        return;
    }
    print_solution(last[x]);
    cout<<x<<' ';
}

void dfs(long x,long dep)
{
    if (dep==n)
    {
        if (su[x+1]){ cout<<1<<' '; print_solution(last[x]);cout<<x<<endl;}
        return;
    }
    for (long i=1;i<=n;i++)
    {
       // cout<<i<<' '<<a[i]<<' '<<su[i+x]<<endl;
        if ((!a[i])&&(su[i+x]))
        {
            //cout<<x<<"  "<<i<<' '<<i+x<<endl;
            a[i]=true;
            last[i]=x;
            dfs(i,dep+1);
            a[i]=false;
            last[i]=0;
        }
    }

}


int main()
{
    //freopen("F.in","r",stdin);
    //freopen("F.out","w",stdout);
    long t=0;
    susu();
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        t++;
        cout<<"Case "<<t<<":"<<endl;
        a[1]=true;
        dfs(1,1);
        cout<<endl;
    }
    return 0;

}

G:poj1979

Red and Black

Description

There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles. 

Write a program to count the number of black tiles which he can reach by repeating the moves described above. 

Input

The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20. 

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows. 

'.' - a black tile 
'#' - a red tile 
'@' - a man on a black tile(appears exactly once in a data set) 
The end of the input is indicated by a line consisting of two zeros. 

Output

For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).

Sample Input

6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0

Sample Output

45
59
6
13

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long n,m,sx,sy;
char a[200][200];
void init()
{
    memset(a,0,sizeof(a));

    for(long i=1;i<=n;i++)
    for(long j=1;j<=m;j++)
    {
        cin>>a[i][j];
        if (a[i][j]=='@')
        {
            sx=i;
            sy=j;
        }
        if ((a[i][j]=='.')||(a[i][j]=='@'))
           a[i][j]=1;
        else a[i][j]=0;
    }
}
long dfs(long i,long j)
{
    long k=1;
    a[i][j]=0;
    if(a[i-1][j]>0)  k+=dfs(i-1,j);
    if(a[i+1][j]>0)  k+=dfs(i+1,j);
    if(a[i][j-1]>0)  k+=dfs(i,j-1);
    if(a[i][j+1]>0)  k+=dfs(i,j+1);
    return k;

}


int main()
{
 
    cin>>m>>n;
    while ((m!=0)&&(n!=0))
    {
        init();
        cout<<dfs(sx,sy)<<endl;
        cin>>m>>n;
    }

    return 0;

}


H:hdu1515

Anagrams by Stack

Problem Description
How can anagrams result from sequences of stack operations? There are two sequences of stack operators which can convert TROT to TORT: 

[
i i i i o o o o
i o i i o o i o
]

where i stands for Push and o stands for Pop. Your program should, given pairs of words produce sequences of stack operations which convert the first word to the second.

A stack is a data storage and retrieval structure permitting two operations: 

Push - to insert an item and
Pop - to retrieve the most recently pushed item 
We will use the symbol i (in) for push and o (out) for pop operations for an initially empty stack of characters. Given an input word, some sequences of push and pop operations are valid in that every character of the word is both pushed and popped, and furthermore, no attempt is ever made to pop the empty stack. For example, if the word FOO is input, then the sequence: 

i i o i o o is valid, but 
i i o is not (it's too short), neither is 
i i o o o i (there's an illegal pop of an empty stack) 

Valid sequences yield rearrangements of the letters in an input word. For example, the input word FOO and the sequence i i o i o o produce the anagram OOF. So also would the sequence i i i o o o. You are to write a program to input pairs of words and output all the valid sequences of i and o which will produce the second member of each pair from the first.
 

Input
The input will consist of several lines of input. The first line of each pair of input lines is to be considered as a source word (which does not include the end-of-line character). The second line (again, not including the end-of-line character) of each pair is a target word. The end of input is marked by end of file.
 

Output
For each input pair, your program should produce a sorted list of valid sequences of i and o which produce the target word from the source word. Each list should be delimited by 

[
]

and the sequences should be printed in "dictionary order". Within each sequence, each i and o is followed by a single space and each sequence is terminated by a new line.
 

Sample Input
   
   
   
   
madam adamm bahama bahama long short eric rice
 

Sample Output
   
   
   
   
[ i i i i o o o i o o i i i i o o o o i o i i o i o i o i o o i i o i o i o o i o ] [ i o i i i o o i i o o o i o i i i o o o i o i o i o i o i o i i i o o o i o i o i o i o i o i o ] [ ] [ i i o i o i o o ]

个人觉得这是这八个题里最有趣的一个,用string模拟栈

dfs函数里i表示在栈里的o表示已经出栈的,step的记录的方案

dfs里三种情况

1.全部元素已经出栈——达到目标

2.还有元素没有进栈——执行进栈操作

3.栈顶元素与目标一致——栈顶出栈

想清楚就很好搞定了!!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
string s,t;
void dfs(string i,string o,string step)
{
    if (o.size()==t.size())
    {
        for (long j=0;j<step.size();j++)
            cout<<step[j]<<' ';
        cout<<endl;
        return;
    }
    if(i.size()+o.size()<s.size())
    {
        long x=i.size()+o.size();
        dfs(i+s[x],o,step+"i");
    }
    if ((s.size()>0)&&(t[o.size()]==i[i.size()-1]))
    {
        o=o+i[i.size()-1];
        i.erase(i.end()-1);
        dfs(i,o,step+"o");
    }
}

int main()
{
   // freopen("H.in","r",stdin);
    //freopen("H.out","w",stdout);
    long cnt=0;
    while(cin>>s>>t)
    {
        //if (cnt!=0) cout<<endl;
        cnt++;
        cout<<"["<<endl;
        if (s.size()==t.size())
            dfs("","","");
        cout<<"]"<<endl;
    }
    return 0;

}


你可能感兴趣的:(算法,搜索)