问题描
小空正在玩一个叫做捡金币的游戏。游戏在一个被划分成 n行 n列的网格状场地中进行。
每一个格子中都放着若干金币,并且金币的数量会随着时间而不断变化。 小空的任务就是在
网格中移动,拾取尽量多的金币。 并且,小空还有一个特殊技能“闪现”, 能帮助她在网格间
快速移动。
捡金币游戏的具体规则如下:在每一秒开始时,每个网格内都会出现一定数量的金币,
而之前在这格没有被拾取的金币就消失了。在游戏开始时,也就是第 1 秒的开始,小空可以
选择任意一个网格作为起点开始本次游戏,并拾取起点内的金币。之后,在下一秒到来前,
小空可以选择走路移动到与她所在的格子上、下、左、右相邻的一个格子中,或者呆在原地
不动,并在下一秒开始时拾取到她所在的格子中的金币。或者,小空可以选择使用闪现技能,
使用一次闪现时,她先选择上、下、左、右一个方向,之后向该方向移动两格。小空可以在
一秒内使用多次闪现,但不能超过 C 次。在一秒内使用的多次闪现必须向同一个方向移动,
若使用 x 次闪现,便可以向一个方向移动正好 2x 格,并且她也只能在下一秒开始时收集到
连续闪现结束后所在的那一格中的金币。如果在某一秒钟小空使用了闪现,那么她就不能选
择通过走路移动了,反过来也是如此。无论走路或者使用闪现,小空都不能移动到整个场地
之外。整个游戏共进行 T 秒,在第 T 秒开始时,小空将会拾取她所在的格子中的金币,并结
束游戏。 小空在整局游戏内一共只能使用最多 W 次闪现。
举个例子,在如下 3*3 的场地中,游戏共进行 3 秒, 下表列出了 3 秒开始时每一格内的
金币数量。

如果小空选择在第 1 行第 1 列开始游戏,那么在第 1 秒开始时她会获得 1 枚金币。接下
来,如果她选择向右走,那么在第 2 秒开始时她会出现在第 1 行第 2 列并获得 3 枚金币。接
下来, 过她选择向下进行 1 次闪现,那么在第 3 秒开始时她会出现在第 3 行第 2 列并获得 2
枚金币,游戏结束, 一共获得 6 枚金币。
又如, 在如下 5*5 的场地中(只列出了第 1 行所含金币数), 游戏共进行 2 秒, 如果小
空选择在第 1 行第 1 列开始游戏, 则她会获得 1 枚硬币,之后若向右连续闪现 2 次,那么在
第 2 秒开始时她会出现在第 1 行第 5 列, 并获得 2 枚硬币,总共获得 3 枚硬币。

现在,给出游戏场地的大小 n,每秒钟开始时各个位置会出现的金币数,小空一秒内最
多使用闪现的次数 C, 小空在整局游戏中使用闪现的最多次数 W,整局游戏的总时间 T,请
你告诉小空她最多可以获得多少枚金币。
【输入】

输入的第 1 行包含 4 个整数 n, C, W, T,意义如问题描述中所述。
接下来包含 n 个 n*n 的矩阵,第 k 个矩阵的第 i 行第 j 列表示第 i 行第 j 列的格子在第 k
秒开始时出现的金币数(记作si,j,k)。 相邻两个矩阵间用一个空行隔开。
【输出】
输出包含一个整数,表示游戏结束时小空最多可以获得的金币数量。
【输入输出样例 1】

coin.in coin.out
3 1 1 3
1 3 4
3 2 1
1 3 2
2 3 1
1 3 2
2 1 4
3 3 1
3 2 1
2 3 1
11

见选手目录下的 coin / coin1.in 与 coin / coin1.out
【输入输出样例 1 说明】
选择在第 1 行第 3 列开始游戏, 获得 4 枚金币;在第 2 秒开始时向下闪现到第 3 行第 3
列, 获得 4 枚金币;在第 3 秒开始时向左走到第 3 行第 2 列,获得 3 枚金币, 游戏结束。一
共获得 11 枚金币。
【输入输出样例 2】
见选手目录下的 coin / coin2.in 与 coin / coin2.out
【数据规模与约定】

测试点编号 n C W T si,j,k
1 ≤5 ≤2 ≤4 ≤5 ≤1,000
2
3
4 ≤21 ≤10 ≤80 ≤80
5
6
7 ≤25 =100 ≤150 ≤100
8
9 ≤12
10

对 100%的数据, n≥1, C≥0, W≥0, T≥1, si,j,k≥0

分析:直接爆搜可以通过30%的数据.其实这道题阶段性特别明显,一眼就能看出是一道dp题,设f[t][k][i][j]表示在第t秒,用了k次闪现,当前位置在(i,j)的答案.转移也非常容易,从上一秒可能的位置上转移就可以了.这样dp只能通过60%的数据,因为状态数很多,每次找闪现的位置会花费大量的时间,必须对闪现的转移进行优化.

在闪现的众多状态中,只需要找到最大的那个就可以了,因为每一轮的C是固定的,可以考虑用单调队列来维护.假设从左往右闪现,闪现一次,f[t][k][i][j]从f[t-1][k-1][i-2][j]转移而来,闪现两次就从f[t-1][k-2][i-4][j]转移而来,t-1,j是固定的,只需要用单调队列维护C个f[t-1][k-p][i-2*p][j]就可以了.

30分暴力:

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ;
const int dx[] = { , -, , }, dy[] = { , , , - }; int n, ans, C, W, T, a[][maxn][maxn];
int vis[][][maxn][maxn]; struct node
{
int x, y, sum, dist, use;
}; bool check(int x, int y)
{
if (x >= && x <= n && y >= && y <= n)
return true;
return false;
} void bfs()
{
queue <node> q;
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
{
node temp;
temp.x = i;
temp.y = j;
temp.sum = a[][i][j];
temp.dist = ;
temp.use = ;
q.push(temp);
}
while (!q.empty())
{
node u = q.front();
q.pop();
int x = u.x, y = u.y, dist = u.dist, use = u.use, sum = u.sum;
if (dist == T)
{
ans = max(ans, sum);
continue;
}
//不闪现
for (int i = ; i < ; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if (check(nx, ny))
{ node v;
v.dist = dist + ;
v.use = use;
v.sum = sum + a[dist + ][nx][ny];
v.x = nx;
v.y = ny;
q.push(v); }
}
//闪现
for (int i = ; use + i <= W && i <= C; i++)
{
for (int j = ; j < ; j++)
{
int nx = x + i * * dx[j], ny = y + i * * dy[j];
if (check(nx, ny))
{
node v;
v.dist = dist + ;
v.use = use + i;
v.sum = sum + a[dist + ][nx][ny];
v.x = nx;
v.y = ny;
q.push(v);
}
}
}
node v;
v.x = x;
v.y = y;
v.dist = dist + ;
v.use = use;
v.sum = sum + a[dist + ][x][y];
q.push(v);
}
} int main()
{
scanf("%d%d%d%d", &n, &C, &W, &T);
for (int k = ; k <= T; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
scanf("%d", &a[k][i][j]);
bfs();
printf("%d\n", ans); return ;
}

60分裸dp:

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ;
const int dx[] = { , -, , }, dy[] = { , , , - }; int n, ans, C, W, T, a[][maxn][maxn];
int f[][][maxn][maxn]; bool check(int x, int y)
{
if (x >= && x <= n && y >= && y <= n)
return true;
return false;
} int main()
{
scanf("%d%d%d%d", &n, &C, &W, &T);
for (int k = ; k <= T; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
scanf("%d", &a[k][i][j]);
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
f[][][i][j] = a[][i][j];
for (int t = ; t <= T; t++)
{
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
for (int k = ; k <= W; k++)
{
for (int p = ; p < ; p++)
{
int nx = i + dx[p], ny = j + dy[p];
if (check(nx, ny))
{
f[t][k][i][j] = max(f[t][k][i][j], f[t - ][k][nx][ny]);
}
for (int l = k - ; k - l <= C; l--)
{
int nx = i + * (k - l) * dx[p],ny = j + * (k - l) * dy[p];
if (check(nx, ny))
{
f[t][k][i][j] = max(f[t][k][i][j], f[t - ][l][nx][ny]);
}
}
}
f[t][k][i][j] = max(f[t][k][i][j], f[t - ][k][i][j]);
f[t][k][i][j] += a[t][i][j];
}
}
}
}
for (int i = ; i <= T; i++)
for (int j = ; j <= W; j++)
for (int k = ; k <= n; k++)
for (int l = ; l <= n; l++)
ans = max(ans, f[i][j][k][l]);
printf("%d\n", ans); return ;
}

AC:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int inf = 0x7fffffff; int n, C, W, T, now, last, tag, head, q[], cnt, tail, cur[], ans;
int a[][][], f[][][][], vis[][]; void init()
{
head = , tail = ;
q[] = -inf;
cnt = ;
} void push(int x)
{
int sum = ;
while (head <= tail && x >= q[tail])
sum += cur[tail--];
q[++tail] = x;
cur[tail] = sum;
if (++cnt > C) //因为有的被弹出来过,可能没有闪现C次
if (--cur[head] == )
head++;
} int main()
{
scanf("%d%d%d%d", &n, &C, &W, &T);
for (int t = ; t <= T; t++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
scanf("%d", &a[t][i][j]);
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
f[][][i][j] = a[][i][j];
last = ;
now = ;
for (int t = ; t <= T; t++)
{
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
for (int k = ; k <= W; k++)
f[now][k][i][j] = -inf;
for (int i = ; i <= n; i++)
{
++tag;
for (int j = ; j <= n; j++)
for (int k = ; k <= W; k++)
if (vis[j][k] != tag)
{
init();
int nj = j, nk = k;
while (nj <= n && nk <= W)
{
vis[nj][nk] = tag;
f[now][nk][i][nj] = max(f[now][nk][i][nj], q[head]);
push(f[last][nk][i][nj]);
nj += ;
nk++;
}
}
++tag;
for (int j = n; j >= ; j--)
for (int k = ; k <= W; k++)
if (vis[j][k] != tag)
{
init();
int nj = j, nk = k;
while (nj >= && nk <= W)
{
vis[nj][nk] = tag;
f[now][nk][i][nj] = max(f[now][nk][i][nj], q[head]);
push(f[last][nk][i][nj]);
nj -= ;
nk++;
}
}
} for (int j = ; j <= n; j++)
{
++tag;
for (int i = ; i <= n; i++)
for (int k = ; k <= W; k++)
if (vis[i][k] != tag)
{
init();
int ni = i, nk = k;
while (ni <= n && nk <= W)
{
vis[ni][nk] = tag;
f[now][nk][ni][j] = max(f[now][nk][ni][j], q[head]);
push(f[last][nk][ni][j]);
ni += ;
nk++;
}
}
++tag;
for (int i = n; i >= ; i--)
for (int k = ; k <= W; k++)
if (vis[i][k] != tag)
{
init();
int ni = i, nk = k;
while (ni >= && nk <= W)
{
vis[ni][nk] = tag;
f[now][nk][ni][j] = max(f[now][nk][ni][j], q[head]);
push(f[last][nk][ni][j]);
ni -= ;
nk++;
}
}
}
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
for (int k = ; k <= W; k++)
{
f[now][k][i][j] = max(f[now][k][i][j], f[last][k][i - ][j]);
f[now][k][i][j] = max(f[now][k][i][j], f[last][k][i + ][j]);
f[now][k][i][j] = max(f[now][k][i][j], f[last][k][i][j - ]);
f[now][k][i][j] = max(f[now][k][i][j], f[last][k][i][j + ]);
f[now][k][i][j] = max(f[now][k][i][j], f[last][k][i][j]);
f[now][k][i][j] += a[t][i][j];
}
swap(now, last);
}
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
for (int k = ; k <= W; k++)
ans = max(ans, f[last][k][i][j]);
printf("%d\n", ans); return ;
}

noip模拟赛 捡金币的更多相关文章

  1. NOIP模拟赛-2018.11.6

    NOIP模拟赛 今天想着反正高一高二都要考试,那么干脆跟着高二考吧,因为高二的比赛更有技术含量(我自己带的键盘放在这里). 今天考了一套英文题?发现阅读理解还是有一些困难的. T1:有$n$个点,$m ...

  2. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  3. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  4. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  5. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  6. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  7. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  8. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  9. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

随机推荐

  1. CF482C Game with Strings

    题意 你和你的朋友玩一个游戏,游戏规则如下. 你的朋友创造 n 个长度均为 m 的不相同的字符串,然后他随机地选择其中一个.他选择这些字符串的概率是相等的,也就是说,他选择 n 个字符串中的每一个的概 ...

  2. 递推DP UVA 1366 Martian Mining

    题目传送门 /* 题意:抽象一点就是给两个矩阵,重叠的(就是两者选择其一),两种铺路:从右到左和从下到上,中途不能转弯, 到达边界后把沿途路上的权值相加求和使最大 DP:这是道递推题,首先我题目看了老 ...

  3. EditText(6)EditText的子类

      1.Known Direct Subclasses AppCompatEditText, AutoCompleteTextView, ExtractEditText, GuidedActionEd ...

  4. mysql-installer-web-community-5.7.18.1.msi的安装(图文详解)

    不多说,直接上干货! 说在前面的话 我为什么已经尝试和使用过同类型产品的很多MySQL版本,还要书写这篇博客呢?基于mysql-installer-web-community-5.7.18.1.msi ...

  5. php简易计算器

    php循环结构 案例:php简易计算器 步骤: 1.先绘制这个表格 2.根据表单提交的sub属性判断一下,是否点击计算了 (GET方式提交的数据,通过地址栏传递的) 3.计算,并将结果输入到第二行 问 ...

  6. python自动化--语言基础四模块、文件读写、异常

    模块1.什么是模块?可以理解为一个py文件其实就是一个模块.比如xiami.py就是一个模块,想引入使用就在代码里写import xiami即可2.模块首先从当前目录查询,如果没有再按path顺序逐一 ...

  7. JS高级——监听浏览器的返回事件

    https://www.cnblogs.com/Easty/p/7820055.html https://www.cnblogs.com/zhengyan/p/6912526.html http:// ...

  8. day18-常用模块III (numpy、pandas、matplotlib)

    目录 numpy模块 创建矩阵 获取矩阵的行列数 切割矩阵 矩阵元素替换 矩阵的合并 通过函数创建矩阵 矩阵的运算 矩阵的点乘与转置 矩阵的逆 矩阵的其他操作 numpy.random生成随机数 pa ...

  9. qemu vm setup network(ssh) with buildroot

    1, build buildroot with buildroot.config, that is 'make qemu_x86_64_defconfig' + some packages, sshd ...

  10. Windows下运行jekyll,编码已不再是问题

    很久没更新jekyll了,所以好奇着去官网看了下更新记录,发现如下更新条目(版本1.3.0/2013-11-04发布): Add encoding configuration option (#144 ...