P1070 道路游戏

斯德哥尔摩

2018-10-26 22:37:15

Personal

[P1070 道路游戏](https://www.luogu.org/problemnew/show/P1070) 这题还是很难的,至少我这么认为。 用一维数组$dp$储存第$i$秒能获得的最大钱数。 因为最多只能存在$1$个机器人,则若第$i$秒时第$j$个机器人走$k$次$(k\in[1,p])$。 那么状态转移方程长这样: $$dp[i]=\max\{dp[i-k]-cost[last]+now\}$$ 这里是从当前点倒推,$last$是上一个点。 当$last==0\text{或}last==n$时,$now$要一遍遍加上钱$k$秒第$last$路上的金币数。 每次减去第$last$条道路(即第$last$个工厂机器人)的价格。 如果$i-k<0$,直接退出$k$循环,因为时间不为负。 因为结果可能是负的,所以初始化为极小值。 一开始$dp[0]=0$,即第$0$秒金币数为$0$。 最后输出第$m$秒的值,即$dp[m]$。 附代码: ```cpp #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define MAXN 1010 using namespace std; int n,m,q; int money[MAXN][MAXN],cost[MAXN],dp[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void work(){ dp[0]=0; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ int t=j-1; if(!t)t=n; int now=money[t][i]; for(int k=1;k<=q;k++){ if(i<k)break; dp[i]=max(dp[i],dp[i-k]+now-cost[t]); t--; if(!t)t=n; now+=money[t][i-k]; } } printf("%d\n",dp[m]); } void init(){ n=read();m=read();q=read(); memset(dp,-127,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) money[i][j]=read(); for(int i=1;i<=n;i++)cost[i]=read(); } int main(){ init(); work(); return 0; } ```