牛客NOIP暑期七天营-普及组4 C-火龙果田

小巫女从小就喜欢吃火龙果,她有一个梦想,就是用魔法变出许许多多美味可口的火龙果,这样她就可以天天享受火龙果的美味啦!

可是小巫女平常没有认真完成魔法学院的功课,魔法经常出现一些意想不到的情形,不能变出许多的火龙果。

于是,在一块 H × W 的田地里,她打算先变出 n 个品种的火龙果,并且种在坐标为 (xi, yi) 的格子内,并且美味程度为 ci ,然后在剩余的格子内种满任意美味程度的火龙果。但是,火龙果们要求相邻格子(指上下左右四个格子)的火龙果的美味程度 ci 的差的绝对值不超过D。

小巫女想知道整块地每个格子美味程度之和的可能值最大是多少。但她忙着施展她的魔法呢,于是她就拜托你来解决这个问题啦!
小巫女的魔法可能不稳定,如果出现了无解的情况,请输出PitayaCrying。

输入描述:

第一行,四个整数H、W、n和D。

接下来 n 行,每行三个整数x、y、c,表示在格子(x, y)的火龙果的价值为c。

(数据保证格子(x, y)在 H × W 的田地)

输出描述:

如果出现了无解的情况,请输出PitayaCrying。
否则你需要输出田地中每个格子美味程度之和对109 + 7 取模后的结果。

示例1

输入

复制

2 3 2 2
2 1 4
1 2 7

输出

复制

40

示例2

输入

复制

3 1 2 100
1 1 1
3 1 202

输出

复制

PitayaCrying

示例3

输入

复制

2 2 3 2
2 1 1
2 2 4
1 1 1

输出

复制

PitayaCrying

示例4

输入

复制

2 2 3 2
1 1 3
1 1 2
1 1 2

输出

复制

PitayaCrying

备注:

 

思路

为了保证美味程度(c)之和最大,应从已知的最小的c开始,找四周的格子,如果格子已知,判断两者的差值是否不超过D,如果格子未知,再判断未知格子四周的格子,找到已知的四周的格子的上界与下界的交集,然后将交集的最大值赋予该未知格子。

这里可以找出四周格子里的最大值和最小值,如果两者差值不超过2D,就是符合条件的,可以赋予未知格子的最大值就是最小值加上D。也可以跟我的代码一样取交集的最大值。

也是为了确保差值最小,每次都从最小的c开始,使用优先队列即可

PS:注意一个坑点,题目给你的n种火龙果里面,有可能(x,y)坐标是一样的,这时候你要判断他们的c的差值,做的人基本都入坑了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define rep1(i,s,e) for(int i=s;i<e;i++)
#define rep2(i,s,e,c) for(int i=s;i>=e;i--)
#define pfi(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pfn() printf("\n")
#define pfs() printf(" ")
#define sfi(x) scanf("%d",&x)
#define sfi1(x,y) scanf("%d%d",&x,&y)
#define sff(x) scanf("%lf",&x)
#define sfl(x) scanf("%lld",&x)
#define memset1(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int MAX = 1e4 + 50;
const int mod = 1e9+7;
struct node{
	int x,y;
	ll c;
	node():x(0),y(0),c(0){}
	node(int _x,int _y,ll _c):x(_x),y(_y),c(_c){}
	bool operator < ( const node & t ) const{
		return c>t.c;
	}
}p,p1,p2;
ll ar[2005][2005];
bool mmap[2005][2005];
int xy[][2]={{1,0},{-1,0},{0,1},{0,-1}};
int main(){
	int h,w,n,d;
	scanf("%d%d%d%d",&h,&w,&n,&d);
	priority_queue<node> q;
	memset1(mmap);
	memset1(ar);
	bool flag=true;
	for(int i=0;i<n;i++){
		scanf("%d%d%lld",&p.x,&p.y,&p.c);
		if(!ar[p.x][p.y]) ar[p.x][p.y]=p.c;
		else if(ar[p.x][p.y]!=p.c) flag=false;
		mmap[p.x][p.y]=true;
		q.push(p);
	}
	if(flag){
		while(q.size()){
			p=q.top();
			q.pop();
			for(int k=0;k<4;k++){
				p2=p;
				p2.x+=xy[k][0]; p2.y+=xy[k][1];
				if(p2.x>=1&&p2.x<=h&&p2.y>=1&&p2.y<=w){
					if(!mmap[p2.x][p2.y]){
						ll left=0,right=0x7f7f7f7f;
						for(int i=0;i<4;i++){
							p1=p2;
							p1.x+=xy[i][0]; p1.y+=xy[i][1];
							if(p1.x>=1&&p1.x<=h&&p1.y>=1&&p1.y<=w&&mmap[p1.x][p1.y]){
								ll left1=ar[p1.x][p1.y]-d,right1=ar[p1.x][p1.y]+d;
								if(right1<left||right<left1){
									flag=false;
									break;
								}
								else{
									if(right1>=left){
										if(right1<=right) right=right1;
										if(left1>=left) left=left1;
									}
									else if(right>=left1){
										if(right>right1) right=right1;
										if(left<left1) left=left1; 
									}
								}
							}
						}
						if(!flag) break;
						mmap[p2.x][p2.y]=true;
						ar[p2.x][p2.y]=right;
						p2.c=right;
						q.push(p2);		
					}
					else if(abs(ar[p2.x][p2.y]-p.c)>d){
						flag=false;
						break;
					}
				}
			}
			if(!flag) break;		
		}	
	}
	if(!flag) printf("PitayaCrying\n");
	else{
		ll ans=0;
		for(int i=1;i<=h;i++){
			for(int j=1;j<=w;j++){
				ans=(ans+ar[i][j])%mod;
			}
		}	
		pfl(ans);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值