codevs 搜索题汇总(钻石+大师级)

1043 方格取数

2000年NOIP全国联赛提高组

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
题目描述 Description

设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):

某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。

此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

输入描述 Input Description

输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。

输出描述 Output Description

    只需输出一个整数,表示2条路径上取得的最大的和。

样例输入 Sample Input

      8

      2  3  13

      2  6   6

      3  5   7

      4  4  14

      5  2  21

      5  6   4

      6 3  15

      7 2  14

      0 0  0

样例输出 Sample Output

      67

数据范围及提示 Data Size & Hint
如描述
#include<cstdio>
#include<iostream>
using namespace std;
int a[11][11];
int n,x,y,z;
int f[11][11][11][11]; 
int main()
  {
      scanf("%d",&n);
      do
        {
            scanf("%d%d%d",&x,&y,&z);
            a[x][y]=z;
        }while(x!=0&&y!=0&&z!=0);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
          for(int l=1;l<=n;l++)
              {
                  int x1=0,x2=0,x3=0,x4=0;
                  x1=f[i-1][j][k-1][l];
                  x2=f[i-1][j][k][l-1];
                  x3=f[i][j-1][k-1][l];
                  x4=f[i][j-1][k][l-1];
                  f[i][j][k][l]=max(max(x1,x2),max(x3,x4));
                if((i==k)&&(j==l))
                  f[i][j][k][l]+=a[i][j];
                else
                  f[i][j][k][l]+=(a[i][j]+a[k][l]); 
              }
    printf("%d",f[n][n][n][n]);
      return 0;
  }
View Code
 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
题目描述 Description

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入描述 Input Description

输入初试状态,一行九个数字,空格用0表示

输出描述 Output Description

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

样例输入 Sample Input

283104765

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

详见试题

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int c[9]={1,1,2,6,24,120,720,5040,40320};//1,2,3~8的阶乘
int dict2[4]={0,0,1,-1},
    dict1[4]={-1,1,0,0};
int www;
int step[400000];
int steps; 

char  q[400000][9];
char mb[9]={1,2,3,8,0,4,7,6,5};

bool used[400000],sign;

int hash(char str[9])
{
    int i,j,k;
    int f[10];
    int sum=0;
    memset(f,0,sizeof(f));
    for (i=0;i<9;i++)
    {
        k=0;
        for (j=0;j<8;j++)           //找出第一个字符在字符串子串中是第几大。 
            if (j<str[i] && !f[j])
                k++;
        f[str[i]]=1;                //该字符已经判断过,以后的子串的第一个比较时不再和这个比较 
        sum+=k*c[8-i];              //存下an*(n-1)! 
    }            
    return sum;                     //总和 
}
void bfs()
{
    int i,j,h,t;
    int x1,y1,z1,cx,cy,cz;
    memset(used,0,sizeof(used));
    memset(step,0,sizeof(step));
    www=hash(q[0]);
    used[www]=1;
    h=0;                            //队列头尾标记 
    t=1;
    while (h<t)
    {
        sign=0;
        for (i=0;i<9;i++)
        if (q[h][i]!=mb[i])
        {
            sign=true;
            break;
        }
        
        if (!sign)
        {
            steps=step[h];
            return;
        }
        
        for (i=0;i<9;i++)
            if (q[h][i]==0)
            {
                x1=i/3;
                y1=i%3;
                z1=i;
                break;
            }
        for (i=0;i<4;i++)
        {
            cx=x1+dict1[i];
            cy=y1+dict2[i];
            cz=cx*3+cy;
            if ((cx>=0) && (cx<3) && (cy>=0) && (cy<3))
            {
                for (j=0;j<9;j++)
                    q[t][j]=q[h][j];
                q[t][z1]=q[h][cz];
                q[t][cz]=0;
                www=hash(q[t]);
                if (!used[www])
                {
                    used[www]=1;
                    step[t]=step[h]+1;
                    t++;
                }
            }
        }
        h++;
    }
    steps=-1;
    return;
}
int main()
{ 
    int i;
    char in[10];
    scanf("%s",in);
    for (i=0;i<9;i++)
        q[0][i]=in[i]-'1'+1;
    bfs();
    printf("%d",steps);
    return 0;
}
View Code
 时间限制: 2 s
 空间限制: 8000 KB
 题目等级 : 钻石 Diamond
题目描述 Description

在一个n*m的方阵中

寻找somebody的位置

有可能k不存在输出“biantai”

输入描述 Input Description

共n+1行

第一行 n m k

后n行为方阵

输出描述 Output Description

输出k的行和列

样例输入 Sample Input

2 4 9

1 1 4 5

5 9 4 0

样例输出 Sample Output

2 2

数据范围及提示 Data Size & Hint

n<10 m<10

有可能k不存在输出“biantai”

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,k;
int a[11][11];
int x;
int main()
  {
      scanf("%d%d%d",&n,&m,&k);
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          {
              scanf("%d",&x);
              if(x==k)
                {
                    printf("%d %d",i,j);
                    return 0;
                }
          }
    printf("biantai
");
      return 0;
  }
View Code
原文地址:https://www.cnblogs.com/yuemo/p/5591622.html