记忆化搜索

Posted gcfer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记忆化搜索相关的知识,希望对你有一定的参考价值。

直接上题:

技术图片

本题就是求在m的情况下,那些点能通过吃其他的点,强化自己然后留到最后(挺像大鱼吃小鱼的)。

没错,这就是挂我暴力的题,本来50分的暴力,因为没开longl long只剩可怜的十几分,算了,长个教训吧!

我们刚开始的思想就暴力呗!暴力检查每个点能否扩到最后,然后输出!

显然非正解...

显然最大的点一定是必胜点,那我们再深入思考,必胜点都有什么性质:假如a是必胜点,而b再加强一部分后能吃掉a,那b显然也一定是必胜点!

之后我们再考虑一个点x可以没有m限制的区间,那就是左右两边第一个比m大的数。

没有m,x依然可以在这个区间里随便吃,知道碰到第一个比他大的数,需要验证了。

如果设想p,q分别为第一个比m大的数,如果p是必胜点,而x能吃掉p,那显然x也是必胜点;

可如果p不是必胜点呢?x也一定不是必胜点,为什么呢?因为p比x大而检查p时也一定加上x的那个区间,但p不是必胜点,则x也一定不是必胜点了。

这样一个数的判断依赖于左右两个点的判断,即想知道x,必须知道p,q;这样搞一个记忆化搜索,就可以O(n)求解了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=8100000;
ll n,m,a[N],vis[N],l[N],r[N],top,maxx,sum[N];
struct zhan

    ll s,id;
;
zhan q[N];
inline ll read()

    ll x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch))if(x==-) ff=-1;ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48);ch=getchar();
    return x*ff;

inline void put(ll x)

    if(x<0) putchar(-),x=-x;
    if(x>9) put(x/10);
    putchar(x%10+0);

inline void dfs(int x)

    ll ans=sum[r[x]-1]-sum[l[x]];
    if(l[x]!=0&&ans+m>=a[l[x]])
    
        if(!vis[l[x]]) dfs(l[x]);
        if(vis[l[x]]==1) vis[x]=1;
    
    if(r[x]!=n+1&&ans+m>=a[r[x]])
    
        if(!vis[r[x]]) dfs(r[x]);
        if(vis[r[x]]==1) vis[x]=1;
    
    if(!vis[x]) vis[x]=-1;
    return ;

int main()

    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i]=read(),maxx=max(maxx,a[i]),sum[i]=sum[i-1]+a[i];
    a[0]=a[n+1]=1e18;
    q[++top].s=a[0];q[top].id=0;
    for(int i=1;i<=n;i++)
    
        if(a[i]==maxx) vis[i]=1;
        while(top&&a[i]>=q[top].s) top--;
        l[i]=q[top].id;
        q[++top].s=a[i];q[top].id=i;
    
    top=0;q[++top].s=a[n+1];q[top].id=n+1;
    for(int i=n;i>=1;i--)
    
        while(top&&a[i]>=q[top].s) top--;
        r[i]=q[top].id;
        q[++top].s=a[i];q[top].id=i;
    
    for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); 
    for(int i=1;i<=n;i++) if(vis[i]==1) put(i),putchar( );
    return 0;
 

 

以上是关于记忆化搜索的主要内容,如果未能解决你的问题,请参考以下文章

hdu1078 记忆化搜索

背包问题 (记忆化搜索)

搜索分析(DFSBFS递归记忆化搜索)

记忆化搜索

wenbao与记忆化搜索

棋盘分割(记忆化搜索)