一、题目链接
https://codeforces.com/contest/1293/problem/D
二、题意
第一行给出一个点的坐标 、 ,以及 、 、 、 。
当 i > 0 时,第i个点的坐标:
= * +
= * +
给出起始点 、 ,开始移动。每一步可以横向或纵向移动一个单位长度,记为1步。问限定t步内,至多可以采集多少点。
三、数据范围
1 ≤ , ≤
2 ≤ , ≤ 100
0 ≤ , ≤
1 ≤ , , t ≤
四、解题思路
先看数据范围,哎鸭,怎么这么大,不会了不会了。
再看一眼,发现2 ≤ , ≤ 100 在一堆long long型中格外醒目。尤其是下界“2"——这意味着每个点的横纵坐标 、 至少是 、 的两倍!由指数增长趋势,后面的点会离得越来越远的!
那么, 就显得格外渺小啦。 都有 了,平面上最多就几十个点,我才不怕呢~
又由于指数增长的特点,第i个点和第0个点的曼哈顿距离(横轴差与纵轴差绝对值的和)总小于第i个点到第i+1个点(分解到x、y轴,用指数模型理解即可)。
所以,从任意点出发,先尽可能收集左边点,有剩余步数再收集右边点,一定是最优的解法。 大!胆!贪!心!
//区间dp也可做,在这里就略了
五、AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x[100], y[100], ax, ay, bx, by, xs, ys, t;
int ans;
int main()
{
cin >> x[0] >> y[0] >> ax >> ay >> bx >> by >> xs >> ys >> t;
int num = 0;
while(1) //把点记录好
{
num++;
x[num] = x[num - 1] * ax + bx;
y[num] = y[num - 1] * ay + by;
if (x[num] > xs && y[num] > ys && x[num] - xs + y[num] - ys > t) break;
//压根走不到的点就不用记录啦
}
for (int i = 0; i <= num; i++) //枚举以i为起点开始收集的情况,取最大解为ans
{
ll sum = abs(xs - x[i]) + abs(ys - y[i]);
//sum记录步数,初始为从起点到i点的步数
if (sum > t) continue;
int now = 1; //now是以i为起点能收集的点数,现在已经收集了i点,now++
int l = i; //向左找
while(l > 0 && sum + x[i] - x[l - 1] + y[i] - y[l - 1] <= t) l--;
//能走到的最小点
sum += (x[i] - x[l] + y[i] - y[l]) * 2;
//由于曼哈顿距离特点,逐点计算步数与直接从i走到最小点的步数相等,所以直接找最小点计算
//*2是算上从最小点返回的步数
now += i - l; //更新在左边收集的点数
int r = i; //向右找
while(x[r + 1] > 0 && sum + x[r + 1] - x[i] + y[r + 1] - y[i] <= t) r++;
now += r - i;
//因为在循环里就限定了sum不会越界,所以不需要再判断sum,now一定是可行的方案
ans = max(ans, now);
}
cout << ans;
return 0;
}