模拟题:
此四件事的单位时间为1;
1:从路边可以跳到第一行的任意一块地上。
2:摘花生。
3:当前的地里可以跳到前、后、左、右的地中。
4:从地中跳到路上。
自己的思路:
从最多的花生地开始摘。
所以写了个快排....
每次都要判断:到下一块花生地的时间, 摘花生, 再回到路上的总时间是否大于限定时间。
若超出限定时间, 当所摘的花生数即为所求。
没超出限定时间:limit >= time(总花时间)。
总结:
在求:去下一块花生地, 摘花生, 回到路上的时候, 没有用到绝对值判断, 生硬地自己判断
八个方位, 累死了...还是错的...唉, 居然占了1500多KB的code...
最后才有点感觉用绝对值判断....写五六行就搞定...悲剧
特别要留心的时求取next_time时有一段返回路边的时间是重复的, 没调出来的时候也忘了减,
还好错了第一次后, 自己慢慢调了出来...
Accepted 260kB 0ms 3533 B G++
#include <stdio.h>
#include <stdlib.h>
#define ZERO 0
/* 花生的位置 */
typedef struct {
int x;
int y;
int value;
}Pos;
/* 递减排序(花生个数各不相同) */
void quick_sort(Pos *peanut, Pos *begin, Pos *end)
{
Pos tmp, *i, *j;
if (begin >= (end - 1))
{
return;
}
i = begin;
j = end - 1;
tmp = *peanut;
while (i < j)
{
while (i < j && tmp.value >= j->value )
{
j--;
}
if (i < j)
{
*i = *j;
i++;
}
while (i < j && tmp.value <= i->value )
{
i++;
}
if (i < j)
{
*j = *i;
j--;
}
}
*j = tmp;
quick_sort(peanut, begin, j + 1); /* 左边 */
quick_sort(j + 1, j + 1, end); /* 右边 */
}
/* 花生地内, 从当前花生地到下一花生地,摘完花生, 返回路边的时间 */
int next_pick(Pos from, Pos to)
{
int m, n, cnt; /* cnt:from 到 to, 摘, 回到路上的时间 */
m = (from.x - to.x) > 0 ? (from.x - to.x) : (to.x - from.x);
n = (from.y - to.y) > 0 ? (from.y - to.y) : (to.y - from.y);
/* from 到 to:m + n, 摘:1, 回到路上:to.x */
cnt = m + n + 1 + to.x;
return cnt;
}
/* 摘花生 */
int pick_peanuts(Pos *peanut, int len, int limit)
{
/* time为总时间, next_time为从当前位置到下一花生地, 摘花生,返回路边的时间 */
int i, cnt, time, next_time;
/* 摘花生的数量cnt, 下一个花生地peanut[i] */
/* time: 从路跳到第一块地(1), 再到第一块花生地(peatnut[i].dot.y - 1),
摘一下(1), 返回路边第一块地(peatnut[i].dot.y - 1), 跳到路上(1) */
time = cnt = i = 0;
next_time = 1 + (peanut[i].x - 1) + 1 + (peanut[i].x - 1) + 1;
time += next_time;
if (next_time > limit) /* 时间不够摘第一个 */
{
return 0;
}
while (limit >= time && i < len) /* 限定时间大于摘下一块花生的总时间 */
{
cnt += peanut[i].value; /* 摘花生 */
time -= peanut[i].x;
i++; /* 下一块花生地 */
if (i < len && i != (len - 1)) /* 存在这块花生地, 且不是最后一块 */
{
/* next_time:去到那块花生地, 摘, 返回路边上第一块地, 跳出 */
next_time = next_pick(peanut[i-1], peanut[i]);
time += next_time;
}
else /* 最后一块地 */
{
/* 去最后一块花生地 */
if (peanut[i].x - peanut[i-1].x > 0)
{
time += (peanut[i].x - peanut[i-1].x);
}
else
{
time += (peanut[i-1].x - peanut[i].x);
}
if (peanut[i].y - peanut[i-1].y > 0)
{
time += (peanut[i].y - peanut[i-1].y);
}
else
{
time += (peanut[i-1].y - peanut[i].y);
}
time += 1; /* 摘一下 */
time += (peanut[i].x-1 + 1); /* 返回路边上第一块地, 跳到路上 */
}
}
return cnt;
}
int main()
{
/* cas测试数据组数, m*n矩阵, time限时, value花生 */
int cas, m, n, time, value, i, j, len;
Pos *peanut = NULL; /* 三元组花生地 */
scanf("%d", &cas);
while ( cas-- )
{
scanf("%d%d%d", &m, &n, &time);
if ((peanut=(Pos *) calloc (m * n, sizeof(Pos))) == NULL) {
printf("空间分配失败!\n");
exit(-1);
}
/* 三元组的初始化 */
len = 0;
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
scanf("%d", &value);
if (value != ZERO)
{
peanut[len].x = i;
peanut[len].y = j;
peanut[len].value = value;
len++;
}
}
}
quick_sort(peanut, peanut, peanut + len); /* 按权值递减排序 */
value = pick_peanuts(peanut, len, time); /* 统计 */
printf("%d\n", value); /* 输出规定时间摘花生总数 */
free( peanut );
peanut = NULL;
}
return 0;
}
描述
鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边
的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!——熊字”。鲁宾逊先生和
多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,
花生植株整齐地排列成矩形网格(如图1)。有经验的多多一眼就能看出,每棵花生植株下
的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘
它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,
不过你一定要在我限定的时间内回到路边。”
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:
1) 从路边跳到最靠近路边(即第一行)的某棵花生植株;
2) 从一棵植株跳到前后左右与之相邻的另一棵植株;
3) 采摘一棵植株下的花生;
4) 从最靠近路边(即第一行)的某棵花生植株跳回路边。
现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?
注意可能只有部分植株下面长有花生,假设这些植株下的花生个数各不相同。
例如在图2所示的花生田里,只有位于(2, 5), (3, 7), (4, 2), (5, 4)的植株下长有花生,
个数分别为13, 7, 15, 9。沿着图示的路线,多多在21个单位时间内,最多可以采到37个花生。
输入
输入的第一行包括一个整数T,表示数据组数
每组输入的第一行包括三个整数,M, N和K,用空格隔开;表示花生田的大小为M * N
(1 <= M, N <= 50),多多采花生的限定时间为K(0 <= K <= 1000)个单位时间。
接下来的M行,每行包括N个非负整数,也用空格隔开;第i + 1行的第j个整数Pij
(0 <= Pij <= 500)表示花生田里植株(i, j)下花生的数目,0表示该植株下没有花生。
输出
输出包括T行,每一行只包含一个整数,即在限定时间内,多多最多可以采到花生的个数
样例输入
6 7 21
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0
样例输出
37