码迷,mamicode.com
首页 > 其他好文 > 详细

P1070道路游戏题解

时间:2019-12-12 18:03:00      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:设置   space   algorithm   mon   一个   优化   print   题解   sizeof   

日常吐槽

作为hin久hin久以前考试考到过的一道题窝一直咕咕咕到现在才想起来去做因为讲解都忘干净了然后自己重新考虑发现被卡了3天

题面

技术图片
技术图片
技术图片

看到题目发现这题的dp状态似乎有点不是很明确?
我们来理一理题目的限制以及我们要干什么。
每条路上出现的金币数量受时间和地点的限制。所以我们至少要用到一个二维的东西。
题目中说当机器人消失的时候需要在任意一个工厂购买机器人,所以\(dp\)的状态表示貌似和地点没什么关系的亚子。但是地点又限制了金币的数量,这怎么搞?
我们可以把走一段路获得的金币数量预处理出来嘛。
\(sum[i][j]\)表示在时刻\(i\),从0时刻的第1个工厂走到了第\(j\)个工厂的能捡到的金币,即不扣除买机器人的钱(在哪里买机器人是\(dp\)中要干的事,这里只是预处理)。在这里设\(money[i][j]\)表示时刻\(j\),第\(i\)条路上出现的金币数量。那么\(sum[i][j]=sum[i-1][jian(j,1)]+money[jian(j,1)][i]\)。其中\(jian(i,j)\)表示\(j\)工厂往前走\(i\)步到达的工厂。
辣么转移方程也就呼之欲出了。\(dp[i]=max\{ dp[i-j]+sum[i][k]-sum[i-j][jian(k,j)]-cst[jian(k,j)]\}\),\(cst[i]\)表示在第\(i\)个工厂购买机器人花的钱。
代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<ctime>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
const int inf=2147483647;
inline int read()
{
    char ch=getchar();
    int x=0; 
    bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return f?-x:x;
}
int n,m,p,mon[1009][1009],cst[1009];
int dp[1009],sum[1009][1009];
inline int jian(int i,int k)
{
    int qwq=(i-k+n)%n;
    return qwq?qwq:n;
}
int main()
{
   freopen("1.in","r",stdin);
    n=read();m=read();p=read();
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
      mon[i][j]=read();//money在这里简写为mon
    for(int i=1;i<=n;i++)
     cst[i]=read();
    for(int i=1;i<=m;i++)
     for(int j=1;j<=n;j++)
      sum[i][j]=sum[i-1][jian(j,1)]+mon[jian(j,1)][i];//,printf("sum[%d][%d]=%d\n",i,j,sum[i][j]); 
    memset(dp,-0x3f,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=p;j++)//枚举步数
        {
            for(int k=1;k<=n;k++)//枚举地点
             if(i-j>=0)
              dp[i]=max(dp[i],dp[i-j]+sum[i][k]-sum[i-j][jian(k,j)]-cst[jian(k,j)]);
        } 
    }
    printf("%d",dp[m]); 
} 

我们发现上面的方程需要枚举地点,它是个三维的,会\(TLE\)(当然因为现在机子跑的快是可以卡过的),我们要想办法优化。
时间肯定是不能省略的,那剩下的就是步数和地点。我们肯定要把一维优化掉。思考哪个看起来更好搞一些。地图是个环,看起来很麻烦的亚子,所以我们把步数优化掉。
把方程中不需要枚举步数的项提出来:
\(dp[i]=max\{dp[i-j]-sum[i-j][jian(k,j)]-cst[jian(k,j)]\}+sum[i][k]\)
由于步数是要被优化掉的,所以我们保留时间和地点两个状态,设置辅助变量\(qwq[i][j]=dp[i]-sum[i][j]-cst[j]\)
新的方程:\(dp[i]=max\{qwq[i-k][j-k]\}+sum[i][j]\),其中k枚举步数,我们要优化掉这一维,发现第二维每次枚举的时候会+1,于是可以各种乱搞
由于博主用不优化的代码卡过了所以优化代码先咕咕咕叭
(逃)
(害怕被打.jpg)

P1070道路游戏题解

标签:设置   space   algorithm   mon   一个   优化   print   题解   sizeof   

原文地址:https://www.cnblogs.com/lcez56jsy/p/12023948.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!