搜索好题集合1

POJ - 2488 Knight’s Journey

Background
The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey
around the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans?

Problem
Find a path such that the knight visits every square once. The knight can start and end on any square of the board.
Input
The input begins with a positive integer n in the first line. The following lines contain n test cases. Each test case consists of a single line with two positive integers p and q, such that 1 <= p * q <= 26. This represents a p * q chessboard, where p describes how many different square numbers 1, … , p exist, q describes how many different square letters exist. These are the first q letters of the Latin alphabet: A, …
Output
The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Then print a single line containing the lexicographically first path that visits all squares of the chessboard with knight moves followed by an empty line. The path should be given on a single line by concatenating the names of the visited squares. Each square name consists of a capital letter followed by a number.
If no such path exist, you should output impossible on a single line.
Sample Input
3
1 1
2 3
4 3
Sample Output
Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4
题面唬人,其实就是一只马问你能不能跳完棋盘所有点.
嗯直接dfs从a1开始搜,搜字典序最小(题意),应该是可以证明如果以a1(或其他任一点)出发没有结果就是不行(显然成立,因为每个点都要到一次吗).所以这样就ok啦.

#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#define pii pair<int,int>
using namespace std;
bool mp[30][30]={0};int p,q;stack<pii> ans;
bool dfs(int x,int y,int cnt)
{   if(x<1||x>p||y<1||y>q)return false;
    if(mp[x][y])return false; 
    if(cnt==p*q){ans.push(pii(x,y));return true;}
    mp[x][y]=1;
    if(dfs(x-1,y-2,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x+1,y-2,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x-2,y-1,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x+2,y-1,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x-2,y+1,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x+2,y+1,cnt+1))
    {ans.push(pii(x,y));return true;}   
    if(dfs(x-1,y+2,cnt+1))
    {ans.push(pii(x,y));return true;}
    if(dfs(x+1,y+2,cnt+1))
    {ans.push(pii(x,y));return true;}
    mp[x][y]=0;
    return false;
}
int main()
{
    int n,cas=0;
    scanf("%d",&n);
    while(n--)
    {   memset(mp,0,sizeof mp);
        scanf("%d%d",&p,&q);
        dfs(1,1,1);
        printf("Scenario #%d:\n",++cas);
        if(ans.empty())printf("impossible");
        else while(!ans.empty()){
            printf("%c%d",(char)(ans.top().second+'A'-1),ans.top().first);
            ans.pop();
        }
        printf("\n\n");
    }
}

写蠢了,忘记向量这玩意了…

POJ - 3009 Curling 2.0

On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.

Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.

Fig. 1: Example of board (S: start, G: goal)

The movement of the stone obeys the following rules:

At the beginning, the stone stands still at the start square.
The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
Once thrown, the stone keeps moving to the same direction until one of the following occurs:
The stone hits a block (Fig. 2(b), (c)).
The stone stops at the square next to the block it hit.
The block disappears.
The stone gets out of the board.
The game ends in failure.
The stone reaches the goal square.
The stone stops there and the game ends in success.
You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.

Fig. 2: Stone movements

扫描二维码关注公众号,回复: 2626892 查看本文章

Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.

With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).

Fig. 3: The solution for Fig. D-1 and the final board configuration

Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets never exceeds 100.

Each dataset is formatted as follows.

the width(=w) and the height(=h) of the board
First row of the board

h-th row of the board

The width and the height of the board satisfy: 2 <= w <= 20, 1 <= h <= 20.

Each line consists of w decimal numbers delimited by a space. The number describes the status of the corresponding square.

0 vacant square
1 block
2 start position
3 goal position
The dataset for Fig. D-1 is as follows:

6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1

Output
For each dataset, print a line having a decimal integer indicating the minimum number of moves along a route from the start to the goal. If there are no such routes, print -1 instead. Each line should not have any character other than this number.

Sample Input
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
Sample Output
1
4
-1
4
10
-1
打冰球,打到障碍可以到障碍前一格并击碎障碍,要保证球有移动空间.
恩也是一个dfs没啥好说的

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int mp[30][30],w,h,bgx,bgy,edx,edy,ans=11;
void dfs(int posx,int posy,int cnt)
{
    int i;
    if(cnt>10)return;
    if(mp[posx-1][posy]!=1)
       for(i=1;posx-i>=1;i++)
          {
            if(mp[posx-i][posy]==3){ans=min(ans,cnt+1);return;}
            if(mp[posx-i][posy]==1){mp[posx-i][posy]=0;dfs(posx-i+1,posy,cnt+1);mp[posx-i][posy]=1;break;}
          }
    if(mp[posx+1][posy]!=1)
       for(i=1;posx+i<=h;i++)
          {
            if(mp[posx+i][posy]==3){ans=min(ans,cnt+1);return;}
            if(mp[posx+i][posy]==1){mp[posx+i][posy]=0;dfs(posx+i-1,posy,cnt+1);mp[posx+i][posy]=1;break;}
          }
    if(mp[posx][posy-1]!=1)
       for(i=1;posy-i>=1;i++)
          {
            if(mp[posx][posy-i]==3){ans=min(ans,cnt+1);return;}
            if(mp[posx][posy-i]==1){mp[posx][posy-i]=0;dfs(posx,posy-i+1,cnt+1);mp[posx][posy-i]=1;break;}
          }
    if(mp[posx][posy+1]!=1)
       for(i=1;posy+i<=w;i++)
          {
            if(mp[posx][posy+i]==3){ans=min(ans,cnt+1);return;}
            if(mp[posx][posy+i]==1){mp[posx][posy+i]=0;dfs(posx,posy+i-1,cnt+1);mp[posx][posy+i]=1;break;}
          }
    return;           
}
int main()
{
    int i,j;
    while(~scanf("%d%d",&w,&h))
    {   memset(mp,0,sizeof mp);
        ans=11;
        if(w==0&&h==0)break;
        for(i=1;i<=h;i++)
          for(j=1;j<=w;j++)
            {
                scanf("%d",&mp[i][j]);
                if(mp[i][j]==2)bgx=i,bgy=j;
                if(mp[i][j]==3)edx=i,edy=j;
            }
        dfs(bgx,bgy,0); 
        ans==11?printf("-1\n"):printf("%d\n",ans);
    }  
}

然而又写蠢了,还是木有用向量…

POJ - 1321 棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1

.

.#
4 4
…#
..#.
.#..

-1 -1
Sample Output
2
1
还是个dfs,有些类似于n皇后,也不多说了

#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#define pii pair<int,int>
using namespace std;
bool mp[10][10]={0},lie[10];int n,k,ans=0;
void dfs(int now,int cnt)
{int i;
    if(now==n+1)
      {if(cnt==k)ans++;
       return;}
    for(i=1;i<=n;i++)
       {if(mp[now][i]==1&&lie[i]!=1)lie[i]=1,dfs(now+1,cnt+1),lie[i]=0;}
    dfs(now+1,cnt);   
}
int main()
{
    int m,i,j,cas=0;char tmp;
    while(~scanf("%d%d",&n,&k))
     {  if(n==-1&&k==-1)break;
        ans=0;
        memset(mp,0,sizeof mp);
        memset(lie,0,sizeof lie);
        for(i=1;i<=n;i++)
          for(j=1;j<=n;j++)
           {scanf(" %c",&tmp);
            if(tmp=='#')mp[i][j]=1;
           }
        dfs(1,0);
        printf("%d\n",ans);
     }
}

POJ - 3278 Catch That Cow

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

  • Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
  • Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input
Line 1: Two space-separated integers: N and K
Output
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input
5 17
Sample Output
4
Hint
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
题意是从一个点走到另一个,可以走+1/-1/*2,问最小的步数
连着做了3道dfs这里没想啥又写了一个dfs,结果…直接re,后来转念一想发现这几乎是个bfs的模板题a!!
gg的dfs代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,ans=1e9,dp[100010];
void dfs(int pos,int cnt)
{ if(dp[pos]<=cnt)return;
  else dp[pos]=cnt; 
  if(pos>=k){ans=min(ans,cnt+pos-k);return;}
  if(pos<k){dfs(pos*2,cnt+1);dfs(pos+1,cnt+1);dfs(pos-1,cnt+1);}          
}
int main()
{   while(~scanf("%d%d",&n,&k))
    {
      memset(dp,127,sizeof dp);
      ans=1e9;
      dfs(n,0);
      printf("%d\n",ans);
    }
}

ac的bfs

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define pii pair<int,int>
using namespace std;
int n,k,ans;bool vis[500010];
void bfs()
{ memset(vis,0,sizeof vis);
  queue<pii>q; 
  q.push(pii(n,0));
  while(!q.empty())
   {
     pii tmp=q.front();q.pop();
     int foot=tmp.second,pos=tmp.first;
     if(pos==k){ans=foot;return;}
     if(!vis[pos*2]&&pos<k)
      {vis[pos*2]=1;q.push(pii(pos*2,foot+1));}
     if(!vis[pos+1]&&pos<k)
      {vis[pos+1]=1;q.push(pii(pos+1,foot+1));}
     if(!vis[pos-1]&&pos>0)
      {vis[pos-1]=1;q.push(pii(pos-1,foot+1));} 

   }  
}
int main()
{   while(~scanf("%d%d",&n,&k))
    { ans=0;
      bfs();
      printf("%d\n",ans);
    }
}

POJ - 1426 Find The Multiple

Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.
Input
The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.
Output
For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.
Sample Input
2
6
19
0
Sample Output
10
100100100100100100
111111111111111111
找一串01序列使其为给出的数字的倍数,
因为保证长度小于等于100,所以一个数位dp就行了.

#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
int n,dp[120][210]={0},end=0;stack<int>ans;
bool dfs(int pos,int sta,bool flg)
{   
    if(dp[pos][sta]==1)return 0;
    if(flg&&sta==0){end=pos;return 1;}
    if(pos<=0)return 0;
    for(int i=0;i<=1;i++)
      {
        if(dfs(pos-1,(sta*10+i)%n,flg||i==1)){ans.push(i);return 1;}
        else dp[pos][sta]=1;
      }
    return 0;     
}
int main()
{
    int tmp;bool flag;
    while(~scanf("%d",&n))
    {   memset(dp,0,sizeof dp);
        end=0;flag=0;
        if(n==0)break;
        dfs(100,0,0);
        while(!ans.empty())
         {  
            tmp=ans.top();
            ans.pop();
            if(tmp==0&&!flag)continue;
            flag=1;printf("%d",tmp);
         }
         for(int i=1;i<=end;i++)
            printf("0");
         printf("\n");   
    }
}

POJ - 3126 Prime Path

The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices.
— It is a matter of security to change such things every now and then, to keep the enemy in the dark.
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.

Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.
— Hmm, in that case I need a computer program to minimize the cost. You don’t know some very cheap software gurus, do you?
— In fact, I do. You see, there is this programming contest going on… Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.
1033
1733
3733
3739
3779
8779
8179
The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.
Input
One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).
Output
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
Sample Input
3
1033 8179
1373 8017
1033 1033
Sample Output
6
7
0
求一个4位质数变成另一个的最短质数路径(即每次变一位,保证变完认为质数)
先筛出到10000的质数,随后bfs即可.

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define pii pair<int,int>
using namespace std;
int mp[10001]={0},from,to,ans;bool vis[10001];
void init()
{
    int i,j;mp[0]=1;
    for(i=2;i<=10000;i++)
      {if(!mp[i])
       for(j=i*2;j<=10000;j+=i)
           mp[j]=1;
      }
}
void bfs()
{   int i;
    queue<pii>q;pii tmp;
    q.push(pii(from,0));
    vis[from]=1;
    while(!q.empty())
    {
        tmp=q.front();q.pop();
        int pos=tmp.first,foot=tmp.second,poss=pos;
        if(pos==to){ans=foot;break;}
        pos=poss-poss%10;
        for(i=0;i<=9;i++)
          if(!vis[pos+i]&&mp[pos+i]==0)q.push(pii(pos+i,foot+1)),vis[pos+i]=1;
        pos=poss-poss%100+poss%10;
        for(i=0;i<=9;i++)
          if(!vis[pos+i*10]&&mp[pos+i*10]==0)q.push(pii(pos+i*10,foot+1)),vis[pos+10*i]=1;
        pos=poss-poss%1000+poss%100;
        for(i=0;i<=9;i++)
          if(!vis[pos+i*100]&&mp[pos+i*100]==0)q.push(pii(pos+i*100,foot+1)),vis[pos+i*100]=1;
        pos=poss-poss%10000+poss%1000;
        for(i=1;i<=9;i++)
          if(!vis[pos+i*1000]&&mp[pos+i*1000]==0)q.push(pii(pos+i*1000,foot+1)),vis[pos+i*1000]=1;     
    }
  return;   
}
int main()
{
    int t;
    scanf("%d",&t);
    init();
    while(t--)
    {   ans=1e9;memset(vis,0,sizeof vis);
        scanf("%d%d",&from,&to);
        bfs();
        ans==1e9?printf("Impossible\n"):printf("%d\n",ans);
    }
}

HDU - 4474 Yet Another Multiple Problem

There are tons of problems about integer multiples. Despite the fact that the topic is not original, the content is highly challenging. That’s why we call it “Yet Another Multiple Problem”.
In this problem, you’re asked to solve the following question: Given a positive integer n and m decimal digits, what is the minimal positive multiple of n whose decimal notation does not contain any of the given digits?
Input
There are several test cases.
For each test case, there are two lines. The first line contains two integers n and m (1 ≤ n ≤ 10 4). The second line contains m decimal digits separated by spaces.
Input is terminated by EOF.
Output
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) while Y is the minimal multiple satisfying the above-mentioned conditions or “-1” (without quotation marks) in case there does not exist such a multiple.
Sample Input
2345 3
7 8 9
100 1
0
Sample Output
Case 1: 2345
Case 2: -1
求在不使用某些数字的情况下构建出为给定数倍数的最小数字.
刚看觉得跟前面那道数位dp很像,想都没想写了一个100位的数位dp,结果wa…后来发现有些数据远超100位(如9731,9,0,1,3,4,5,6,7,8,9),于是怒开1500位数位dp,tle…最后想到用bfs搜余数,a掉…
gg代码:数位dp

#pragma GCC optimize(3)
#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#define pii pair<int,int>
using namespace std;
bool mp[11],dp[1101][10000]={0};int n,cnt,nn;stack<int>ans;
bool dfs(int pos,int sta,bool flg)
{ int up,i;
  if(flg&&dp[pos][sta])return 0;
  if(pos==0)
    {if(sta==0&&flg)return 1;else return 0;}
  for(i=0;i<=9;i++)
    {if(!flg&&i==0)
       if(dfs(pos-1,(sta*10+i)%nn,flg||i!=0))
       {ans.push(i);return 1;}
     if(!mp[i]&&(i!=0||flg))
       if(dfs(pos-1,(sta*10+i)%nn,flg||i!=0))
       {ans.push(i);return 1;} 
    }
  if(flg)dp[pos][sta]=1;
  return 0;
}
int main()
{   int m,i,j,cas=0;int tmp;
    while(scanf("%d%d",&n,&m)!=EOF)
     { memset(mp,0,sizeof mp);
       for(i=1;i<=m;i++)
         {scanf("%d",&tmp);mp[tmp]=1;}
       tmp=n;nn=n;
       dfs(1100,0,0);
       printf("Case %d: ",++cas);
       if(ans.empty())printf("-1");
       else
        {   bool flg=0;
            while(!ans.empty())
             {tmp=ans.top();ans.pop();
              if(flg==0&&tmp==0)continue;
              flg=1;printf("%d",tmp);}
        }
        printf("\n");  
     }
}

ac代码:bfs

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#define pii pair<int,string>
using namespace std;
bool mp[11],vis[10000];int use[11],n,cnt;
void bfs()
{ queue<pii>q;string tmp;int i;
  for(i=1;i<=cnt;i++)
 {tmp=use[i]+'0';q.push(pii(use[i]%n,tmp));vis[use[i]%n]=1;if(use[i]%n==0&&use[i]!=0){cout<<use[i];return;}}
  while(!q.empty())
  {pii now=q.front();q.pop();
   for(i=1;i<=cnt;i++)
     { if((now.first*10+use[i])%n==0&&now.first!=0)
         {bool flg=0;
          for(int j=0;j<now.second.length();j++)
           {if(!flg&&now.second[j]=='0')continue;flg=1;
              cout<<now.second[j];}cout<<use[i];return;}
        if(!vis[(now.first*10+use[i])%n])
        {vis[(now.first*10+use[i])%n]=1;
         q.push(pii((now.first*10+use[i])%n,now.second+(char)(use[i]+'0')));
        }
     }
  }
  printf("-1");  
}
int main()
{   int m,i,j,cas=0;int tmp;
    while(scanf("%d%d",&n,&m)!=EOF)
     { memset(mp,0,sizeof mp);
       memset(vis,0,sizeof vis);
       cnt=0;
       for(i=1;i<=m;i++)
         {scanf("%d",&tmp);mp[tmp]=1;}
       for(i=0;i<=9;i++)
         if(!mp[i])use[++cnt]=i;  
       printf("Case %d: ",++cas);  
       bfs();printf("\n");
     }
}

总结:要分清什么时候用大法师什么时候用b法师…

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/78461931