浏览器标题切换
浏览器标题切换end

记忆化搜索专题

思想

记忆化搜索的思想无非就是:搜索 + DP

注意!!!

  1. 记忆化搜索要判断是从起点直接搜dfs(0,0)还是for循环遍历每一个点都要去搜!
  2. 判断是否需要标记book,还是book直接作为搜到已经搜过的直接返回的数组!

POJ1088-滑雪

注意:POJ上不能用万能头文件,把头文件注释掉之后用C++提交会无法提交(直接报错:error: bits/stdc++.h: No such file or directory,必须删除才可以。(为啥我也不晓得)

必须删除前几行注释掉的部分:

//#include<bits/stdc++.h>
//using namespace std;
//typedef long long ll;

AC代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d\n",T)
#define f(a,b,c) for (int a=b;a<c;a++)
#define ff(a,b,c) for (int a=b;a>c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)

int a[110][110],n,m,ans,book[110][110];
int to[4][2]= {{0,1},{0,-1},{-1,0},{1,0}};

//void dfs(int x,int y,int cnt)
int dfs(int x,int y)
{
//    if(cnt<=ans)
//        return;
//    ans=max(ans,cnt);
    if(book[x][y])
        return book[x][y];
    //book[x][y]=1;
    f(i,0,4)
    {
        int tx=x+to[i][0];
        int ty=y+to[i][1];
//      if(tx>=0&&tx<n&&ty>=0&&ty<m&&!book[tx][ty])
        if(tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]<a[x][y])
        {
            // book[tx][ty]++; // book[tx][ty]=1;

            //book[tx][ty]=max(book[tx][ty],dfs(tx,ty));
            book[x][y]=max(book[x][y],dfs(tx,ty)+1);

            //book[tx][ty]--; // book[tx][ty]=0;
        }
    }
    return book[x][y];
}

int main()
{
    cin>>n>>m;
    f(i,0,n)
    {
        f(j,0,m)
        cin>>a[i][j]; 
    }
//    dfs(0,0,0);
    ans=0; //小于等于0即可
    f(i,0,n)
    {
        f(j,0,m)
        ans=max(ans,dfs(i,j));
    }
    cout<<ans+1<<endl;
    return 0;
}

HDU1078-FatMouse and Cheese

题意:自行百度。
AC代码:

//#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d\n",T)
#define f(a,b,c) for (int a=b;a<c;a++)
#define ff(a,b,c) for (int a=b;a>c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)

int n,k,ans,a[110][110],book[110][110];
int to[4][2]= {{0,1},{0,-1},{-1,0},{1,0}};

int dfs(int x,int y)
{
    if(book[x][y])
        return book[x][y];
    f(i,0,4)
    {
        f(j,0,k+1)
        {
            int tx=x+to[i][0]*j;
            int ty=y+to[i][1]*j;
            if(tx>=0&&tx<n&&ty>=0&&ty<n&&a[tx][ty]>a[x][y])
                book[x][y]=max(book[x][y],dfs(tx,ty));
        }
    }
    //return book[x][y];
    return book[x][y]+=a[x][y];
}

int main()
{
    while(~scc(n,k),n!=-1||k!=-1)
    {
        mem(book,0);
        f(i,0,n)
        {
            f(j,0,n)
            sc(a[i][j]);
        }
        int w=dfs(0,0);
        //cout<<w<<endl;
        cout<<book[0][0]<<endl;
    }
    return 0;
}

HDU1978-How many ways

记忆化搜索Ac代码:

//#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d\n",T)
#define f(a,b,c) for (int a=b;a<c;a++)
#define ff(a,b,c) for (int a=b;a>c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)

#define mod 10000 //写1e4会报错 可以const int mod=1e4不会报错
int n,m,ans,a[110][110],book[110][110];
int to[2][2]= {{0,-1},{1,0}};

int dfs(int x,int y)
{
    if(book[x][y]!=-1)
        return book[x][y];
    book[x][y]=0;
//    if(x==n-1&&y==m-1)
//    {
//        ans++;
//        return 0;
//    }
//    f(i,0,2)
//    {
//        int tx=x+to[i][0];
//        int ty=y+to[i][0];
//        if(tx>=0&&tx<n&&ty>=0&&ty<m)
//            book[x][y]=(book[x][y]%mod+dfs(tx,ty)%mod)%mod;
//
//    }
    for(int i=0; i<=a[x][y]; i++)
    {
        for(int j=0; j<=a[x][y]-i; j++) //表示消耗那个格子的能量能到达的格子;
        {
            int tx=x+i;
            int ty=y+j;
            if(tx>=0&&tx<n&&ty>=0&&ty<m)
                book[x][y]=(book[x][y]+dfs(x+i,y+j))%mod;
        }
    }
    return book[x][y];
}

int main()
{
    int T;
    sc(T);
    while(T--)
    {
        mem(book,-1);
        ans=0;
        scc(n,m);
        f(i,0,n)
        {
            f(j,0,m)
            sc(a[i][j]);
        }
//        f(i,0,n)
//        {
//            f(j,0,m)
//            dfs(i,j);
//        }
        book[n-1][m-1]=1;
        dfs(0,0);
        cout<<book[0][0]%mod<<endl;
    }
    return 0;
}

这题也可以用DP写,
DP AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string.h>
#include<queue>
#include<iostream>
#include<stack>
using namespace std;
typedef long long ll;
const int mod=1e4;

int a[110][110],dp[110][110];

int main()
{
    int t,n,m;
    cin>>t;
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
            }
        }
        dp[n][m]=1;
        for(int i=n;i>=1;i--)
        {
            for(int j=m;j>=1;j--)
            {
                for(int p=0;p<=a[i][j]&&(i+p<=n);p++)
                {
                    int ww=a[i][j]-p;
                    for(int q=0;q<=ww&&(j+q<=m);q++)
                    {
                        if(p==0&&q==0)
                            continue;
                        dp[i][j]=(dp[i][j]+dp[i+p][j+q])%mod;
                    }
                }
            }
        }
        int w=dp[1][1];
        printf("%d\n",w);
    }
    return 0;
}
posted @ 2020-09-14 22:06  抓水母的派大星  阅读(107)  评论(0编辑  收藏  举报