【解题报告】 openjudge The peanuts 数据结构与算法mooc 内排序

描述
Mr. Robinson and his pet monkey Dodo love peanuts very much. One day while they were having a walk on a country road, Dodo found a sign by the road, pasted with a small piece of paper, saying “Free Peanuts Here! ” You can imagine how happy Mr. Robinson and Dodo were.

There was a peanut field on one side of the road. The peanuts were planted on the intersecting points of a grid as shown in Figure-1. At each point, there are either zero or more peanuts. For example, in Figure-2, only four points have more than zero peanuts, and the numbers are 15, 13, 9 and 7 respectively. One could only walk from an intersection point to one of the four adjacent points, taking one unit of time. It also takes one unit of time to do one of the following: to walk from the road to the field, to walk from the field to the road, or pick peanuts on a point.

这里写图片描述
According to Mr. Robinson’s requirement, Dodo should go to the plant with the most peanuts first. After picking them, he should then go to the next plant with the most peanuts, and so on. Mr. Robinson was not so patient as to wait for Dodo to pick all the peanuts and he asked Dodo to return to the road in a certain period of time. For example, Dodo could pick 37 peanuts within 21 units of time in the situation given in Figure-2.

Your task is, given the distribution of the peanuts and a certain period of time, tell how many peanuts Dodo could pick. You can assume that each point contains a different amount of peanuts, except 0, which may appear more than once.
输入
The first line of input contains the test case number T (1 <= T <= 20). For each test case, the first line contains three integers, M, N and K (1 <= M, N <= 50, 0 <= K <= 20000). Each of the following M lines contain N integers. None of the integers will exceed 3000. (M * N) describes the peanut field. The j-th integer X in the i-th line means there are X peanuts on the point (i, j). K means Dodo must return to the road in K units of time.
输出
For each test case, print one line containing the amount of peanuts Dodo can pick.
样例输入
2
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
6 7 20
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
28
原题链接:http://dsalgo.openjudge.cn/huawen10/2/
emmmm…..最讨厌看到英文题了QAQ,没看清楚还RE了一会儿…
解题思路:
乍一看挺复杂的,但是由于Robbinson先生要的不是最优解(求最优解就完全是另一种问题啦),就是说他并不想要一定时间内拿最多的花生,而是看到哪里多就拿哪个。
因此就把有花生的地方记录下来,从大到小排序,然后逐一判断拿完了之后能不能在限定的时间内回去。
稍微需要注意的是一些边界条件和要不要加一什么的。
以下代码:

#include <iostream>
#include <string>
#include <string.h>
#include <cmath>
using namespace std;
struct peanut
{
    int num;
    int x;
    int y;
};
peanut a[2501];
peanut ta[2501];
long long int ans; //摘到的花生数量
void merge(int left, int right, int middle)
{
    int i, j, index1, index2;
    for (j = left; j <= right; ++j)
        ta[j] = a[j];
    index1 = left;
    index2 = middle + 1;
    i = left;
    while (index1 <= middle && index2 <= right)
    {
        if (ta[index1].num >= ta[index2].num)
        {
            a[i] = ta[index1];
            ++i;
            ++index1;
        }
        else
        {
            a[i] = ta[index2];
            ++i;
            ++index2;
        }
    }
        while (index1 <= middle)
        {
            a[i] = ta[index1]; 
            ++i;
            ++index1;
        }
        while (index2 <= right)
        {
            a[i] = ta[index2];
            ++i;
            ++index2;
        }

}
void mergesort(int left, int right)
{
    int middle;
    if (left < right)
    {
        middle = (left + right) / 2;
        mergesort(left, middle);
        mergesort(middle + 1, right);
        merge(left, right, middle);
    }
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        memset(a, 0, sizeof(a));
        memset(ta, 0, sizeof(ta));
        ans = 0;
        int n, m,k;
        cin >> n >> m>>k;
        int temp = 0; //记录有花生的数组下标
        for(int i=0;i<n;++i)
            for (int j = 0; j < m; ++j)
            {
                int p;
                cin >> p;
                if (p>0)
                {
                    a[temp].num = p;
                    a[temp].x = i;
                    a[temp].y = j;
                    ++temp;
                }
            }
        if (temp == 0) { cout << '0' << endl; continue; }
        mergesort(0, temp - 1);
        int prevx = -1, prevy = a[0].y;
        int ht = 0; //已经消耗的时间
        int i = 0; //摘到第几个位置的花生
        while (1)
        {
            if (i >= temp) break;
            if ((ht + abs(prevx - a[i].x) + abs(prevy - a[i].y) + 1 + a[i].x + 1) <= k)
            {
                ht = ht + abs(prevx - a[i].x) + abs(prevy - a[i].y) + 1;
                prevx = a[i].x;
                prevy = a[i].y;
                ans += a[i].num;
                ++i;
                continue;
            }
            else break;
        }
        cout << ans<<endl;
    }
    //system("pause");
    return 0;
}

转载请注明原文链接。
想要浏览更多的学习内容可以看看博主更多其他的博文哦~
http://blog.csdn.net/weixin_38062864

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值