2003年南海初中 取数

题目

这里写图片描述


解题思路

深度优先搜索+一些剪枝

正解:记忆化搜索

代码

#include<cstdio>
#include<cstring>
#define max(a,b) a>b?a:b
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
using namespace std;
const int ta[4]={-1,0,1,0},tb[4]={0,1,0,-1}; 
int w=1,qq,n,m,ans,a[101][101]; 
bool b[101][101]; 
int read()
{
    int d=1,f=0;char c;
    while((c=getchar())<48||c>57) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
    while((c=getchar())>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
void write(int x)//快速输入输出流
{
    if(x>9) write(x/10);putchar(x%10+48);return;
}
void dfs(int x,int y,int g)//深度优先搜索
{
    if (g==0) { ans=max(ans,1); return;} //特判,请注意题目说的是“递增”的等差数列,假如全部一样的话,就输出1
    if (x<1||y<1||x>n||y>m) {ans=ans>w?ans:w; return;}//边界处理
    for (int kk=0;kk<4;kk++)
     if (a[x+ta[kk]][y+tb[kk]]-a[x][y]==g&&b[x+ta[kk]][y+tb[kk]]==0) 
     {
      b[x][y]=1; w++; 
      dfs(x+ta[kk],y+tb[kk],g); //g为等“差”    
      b[x][y]=0; w--; 
     }
     else ans=ans>w?ans:w; 
}
int main()
{
    n=read(); m=read();
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++)
     a[i][j]=read();
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++)
      for (int k=0;k<4;k++) //四个方向搜索
      if (a[i+ta[k]][j+tb[k]]>=a[i][j])
      { w++; 
        b[i+ta[k]][j+tb[k]]=b[i][j]=1; 
        dfs(i+ta[k],j+tb[k],a[i+ta[k]][j+tb[k]]-a[i][j]); 
        b[i+ta[k]][j+tb[k]]=b[i][j]=0; 
        w--; 
        if (ans==n*m) //如果已经等于n*m就直接输出,因为已经不可有有比这个还大的数
        {write(ans); return 0;
        } 
      }
    write(ans);
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/80374410