<7/31>集训日记

来源:互联网 发布:怎么学软件 编辑:程序博客网 时间:2024/06/11 06:44

    今天尝试了一下杭电的题,先看了有关搜索的课件和例题,大概了解了深搜和广搜,不同的空间遍历顺序,比枚举法快捷,常用于路径寻找。

    先看了一个有关素数环的例题,12020个数摆成一个环,要求相邻的两个数的和是一个素数。

    思路是递归填数,依次判断填入的第i个数是否合法,如果一直到20个全部填完,则可以输出该素数环,若不合法,选择下一种可能。

    关键代码见下图,判断该填数是否合法,判断是否全部填完,若合法且未填完,则递归填下一个数【search(t+1)】。

    然后课件上有一个跳马问题。在5*5格的棋盘上,有一只中国象棋的马,从(1,1)点出发,按日字跳马,它可以朝8个方向跳,但不允许出界或跳到已跳过的格子上,要求在跳遍整个棋盘。这个题和杭电上我准备做的第一题十分相似,所以我将这个题的思路带入了做杭电题的过程中。

    杭电的题比这道例题更多要求的地方是:多组输入输出,路径使用字母加数字的方式表示,以及按照字典排序法输出最优结果。(课件例题是要求输出总方案数)

    以下为我杭电题的代码:

#include<iostream>
#include<string>
using namespace std;
int u[8]={-2,-2, -1,-1, 1, 1, 2, 2},
    v[8]={-1, 1, -2, 2,-2, 2,-1, 1};//八个方向
int a[100][100]={0};
bool b[100][100]={0};
int num=0;//记每一步走在棋盘的哪一格和棋盘的每一格有没有被走过
int search(int,int,int); //以每一格为一个阶段,在每一阶段中试遍8个方向
int print();//展示路径
int p,q;//棋盘大小p*q
int e,f;//e是第几组数据的记录 f是输出数据后跳出用的 f很关键 否则程序很慢
string c;//把坐标转化为字母+数字用的
int main()
{
    e=1;
    int n;
    cin>>n;//多组输入
    while(n--)
    {
   cin>>q>>p;f=0;
   a[1][1]=1;b[1][1]=1; //从(1,1)开始走
   search(1,1,2); //从(1,1)开始搜索第2步该怎样走
   if(num==0) {cout<<"Scenario #"<<e<<":"<<endl;cout<<"impossible"<<endl;e++;}
   num=0;
   cout<<endl;
    }
}
int search(int i,int j,int n)
{
  int k,x,y; //定义局部变量
  if(n>p*q) {print();f=1;return 0;}//达到最大规模 可以输出该方案
  else if(n<=p*q)
   {
     if(f==1) return 0;
     for (k=0;k<=7;k++) //试遍8个方向
     {
       if(f==1) return 0;
       x=i+u[k];y=j+v[k]; //走此方向,得到的新坐标
     if(x<=p&&x>=1&&y<=q&&y>=1&&(!b[x][y]))//判断新坐标是否在棋盘上以及这一格之前是否走过
      {
         b[x][y]=1;
         a[x][y]=n;
         search(x,y,n+1); //从新坐标(x,y)去搜索下一步该如何走
         b[x][y]=0;
         a[x][y]=0;
      }
   }
  }
}
int print()
{
   if (num<1)
    {
     num++;//只输出最优(第一个)结果即可
    cout<<"Scenario #"<<e<<":"<<endl;
    for(int i=1;i<=p*q;i++)//找到第i个到达的点
    {
       for (int h=1;h<=p;h++)//h和g为第i点的横纵坐标
        {
          for (int g=1;g<=q;g++)
          {

                 if(a[h][g]==i)
                 {
                  c=h+'A'-1;//转化为字母形式
                 cout<<c<<g;
                 }
          }
        }
    }
    cout<<endl;
    e++;
   }
}

    在经历了三种不同的错误后,这题终于A了……

    第一次出现CE,这个头文件不能用啊【#include<bits/stdc++.h>】……
    第二次出现WA,输出的那个单词scenario我忘了首字母大写……

    第三次出现PE,输出后少了一个回车……

    第一次交ACM题…以后记住了…

 

    开始看数论内容,今天只看了一些有关容斥原理的,明天一起写好了。