noip2004普及组第2题 花生采摘

2018/12/09 19:46
阅读数 93

题目描述 鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。

鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图11)。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”

我们假定多多在每个单位时间内,可以做下列四件事情中的一件:

  1. 从路边跳到最靠近路边(即第一行)的某棵花生植株;

  2. 从一棵植株跳到前后左右与之相邻的另一棵植株;

  3. 采摘一棵植株下的花生;

  4. 从最靠近路边(即第一行)的某棵花生植株跳回路边。

现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?注意可能只有部分植株下面长有花生,假设这些植株下的花生个数各不相同。

例如在图2所示的花生田里,只有位于(2, 5), (3, 7), (4, 2), (5, 4)(2,5),(3,7),(4,2),(5,4)的植株下长有花生,个数分别为13, 7, 15, 913,7,15,9。沿着图示的路线,多多在2121个单位时间内,最多可以采到3737个花生。

输入输出格式 输入格式: 第一行包括三个整数,M, N和K,用空格隔开;表示花生田的大小为M \times N(1 \le M, N \le 20)M×N(1≤M,N≤20),多多采花生的限定时间为K(0 \le K \le 1000)K(0≤K≤1000)个单位时间。接下来的MM行,每行包括N个非负整数,也用空格隔开;第i + 1行的第j个整数P_{ij}(0 \le P_{ij} \le 500)P ij ​ (0≤P ij ​ ≤500)表示花生田里植株(i, j)(i,j)下花生的数目,00表示该植株下没有花生。

输出格式: 一个整数,即在限定时间内,多多最多可以采到花生的个数。

输入输出样例 输入样例#1: 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 输出样例#1: 37 输入样例#2: 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 输出样例#2: 28 说明 noip2004普及组第2题

题目本身并不是很难。主要是要看到题目规定的并不是要采的最多,必须从大到小,依次采摘,因此我们只贪心就可以,用结构体存下横纵坐标和数量,然后排序,按照排序后的顺序依次采摘,期间计算耗费的时间,每计算一个就要进行判断当前所剩余的时间是否可以回去,当不能回去时则到达上一个点时的采摘量,就是最多的采摘量。(注意计算时的横纵坐标,是根据x算还是y,这个根据自己存储的不同使用的也不同,我在这里傻乎乎的找了好长时间orz)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int pic[50][50];
int ans,n,m,k,cnt,nowx,nowy,tot;
struct edge{
    int x,y,v;
}e[5000];
bool cmp(edge a,edge b){
    return a.v > b.v;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1; i<=n; i++){
        for(int j = 1; j<=m; j++){
            scanf("%d",&pic[i][j]);
            if(pic[i][j]){
                cnt ++;
                e[cnt].x = i;e[cnt].y =j;e[cnt].v = pic[i][j];
            }
        }
    } 
    sort(e+1,e+1+cnt,cmp);	
    if(2*e[1].y + 1 > k){
    	cout << 0;
    	return 0;
    }
    else if(2*e[1].x + 1 == k){
    	cout << e[1].v;
    	return 0;
    }
    nowy = e[1].y;
    for(int i = 1; i<=cnt; i++){
    	tot += abs(nowy - e[i].y) + abs(nowx - e[i].x) + 1; 
        if(tot + e[i].x > k)break;
        nowx = e[i].x;
        nowy = e[i].y;
        ans += e[i].v; 
    }
    cout << ans ;
    
    return 0;
}
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部