现在的位置: 首页 > 综合 > 正文

BZOJ 3628 JLOI2014 天天酷跑 记忆化搜索

2017年05月04日 ⁄ 综合 ⁄ 共 2033字 ⁄ 字号 评论关闭

题意:。。。给定一个矩阵,每个点有一堆金币,自己在(0,1),然后各种跳,求最大收益(具体自己看)

传说中的省选第二题,当时写的爆搜20分,现在想想把深搜改成广搜再加个记忆化不就切了么。。。不过这题要开滚动数组 直接交MLE

正解应该是DP 我实在懒得DP就记忆化搜索了 反复memset那里常数有点大 懒得处理了

我自然溢出的队列居然写挂了。。。直接把h-1写在中括号里会强制类型转换成int导致调用q[-1] 所以只能这样了

交的人好少。。这题也没啥意思 水水就切了

注意这题无论是数组还是读入输出都非常容易弄反 小心点就行

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct abcd{
    int x,y;
    int power,times;
}q[65540],empty;
unsigned short r,h;
int n,m,cost1,cost2,ans=0xefefefef,ansh,ansc;
int height,comble;
int map[30][100100];
int f[2][31][20][6];
int g[2][100100];
void Cheat()
{
    int i;
    for(i=1;i<=n;i++)
    {
        if(~map[1][i]) g[0][i]=max( g[0][i-1] , g[1][i-1] )+map[1][i];
        else           g[0][i]=0xefefefef;
        if(~map[2][i]) g[1][i]=     g[0][i-1]              +map[2][i];
        else           g[1][i]=0xefefefef;
    }
    ans=max(g[0][n],g[1][n]);
    if(ans<0)
        puts("mission failed");
    else
        printf("%d %d %d\n",ans,1,1);
    exit(0);
}
void Move(abcd now,int x,int y,int power,int times)
{
    if( ~map[y][x]  )
    {
        if(f[x&1][y][power][times]<0)
        {
            q[++r].x=x;
            q[r].y=y;
            q[r].power=power;
            q[r].times=times;
        }
        f[x&1][y][power][times]=max(f[x&1][y][power][times],f[now.x&1][now.y][now.power][now.times]+map[y][x]);
    }
}
void Memory_Search()
{
    int nowans=0xefefefef;
    r=h=0;
    q[0]=empty;
    q[++r]=q[0];
    q[r].y=1;
	memset(f,0xef,sizeof f);
	f[0][1][0][0]=0;
    while(r!=h)
    {
    	abcd now=q[++h];--h;
        if(now.x!=q[h].x)
        	memset(f[~now.x&1],0xef,sizeof f[0]);
		++h;
        if(now.x==n)
        {
            nowans=max(nowans,f[now.x&1][now.y][now.power][now.times]);
            continue;
        }
        if(now.power)
        {
            Move(now,now.x+1,now.y+1,now.power-1,now.times);
            continue;
        }
        if(now.y==1)
        {
            Move(now,now.x+1,1,0,0);
            Move(now,now.x+1,2,height-1,1);           
        }
        else
        {
            if(now.times!=comble)
                Move(now,now.x+1,now.y+1,height-1,now.times+1);
            Move(now,now.x+1,now.y-1,0,now.y==2?0:now.times);
        }
    }
    nowans-=(height-1)*cost1+(comble-1)*cost2;
    if(nowans>ans)
        ans=nowans,ansh=height,ansc=comble;
}
int main()
{
	
	//freopen("parkour.in","r",stdin);
	//freopen("parkour.out","w",stdout);
	
    int i,j;
    cin>>n>>m>>cost1>>cost2;
    for(i=1;i<=m;i++)
        for(j=1;j<=n;j++)
            scanf("%d",&map[i][j]);
    if(m==2)
        Cheat();
    for(comble=1;comble<=5;comble++)
        for(height=1;comble*height<m;height++)
            Memory_Search();
    if(ans<0)
        puts("mission failed");
    else
        printf("%d %d %d\n",ans,ansc,ansh);
}

抱歉!评论已关闭.