zoj 1021

解析见注释。。。。。。

#include<iostream>
#include<list>
#include<queue>
#include<set>
#include<memory>
#include<cstring>

using namespace std;

int t,p,I,total;
int x[30],up[30], down[30], p_length[30],water[30];
list<pair<int, int> > pipe[30];//对应的水面高度以及管道的编号
int target, level;
priority_queue<pair<int, int> > pq;
bool answer;
set<int> link;

void solve(){
	while (!pq.empty()) pq.pop();
	water[0] = down[0];
	pq.push(make_pair(water[0],0));
	while (!pq.empty()){
		int height = pq.top().first;
		int number = pq.top().second;
		pq.pop();
		if (number == -1) break;//表示溢出
		if (number == -2){//表示可以淹没level
			answer = true;
			break;
		}
		total += (water[number]-height);
		water[number] = height;
		while (!pipe[number].empty() 
			&& pipe[number].front().first == height){
			int flag = pipe[number].front().second;
			if (flag < 0){
				pq.push(pipe[number].front());
			}
			else if (water[flag]==-1){
				water[flag] = down[flag];
				pq.push(make_pair(water[flag],flag));
			}
			pipe[number].pop_front();
		}
		if (!pipe[number].empty())
			pq.push(make_pair(pipe[number].front().first,number));
	}
}


int main(){
	cin >> t;//输入Case数量
	while (t--){
		link.clear();//每一次处理之前清空link
		cin >> p;//管道的数量
		memset(water,-1,sizeof(water));
		for (int i = 0; i < p; i++){
			cin >> x[i] >> up[i] >> p_length[i];//输入对应管道的信息
			down[i] = up[i] + p_length[i];//计算出对应管道的下平面位置
			pipe[i].clear();
		}
		cin >> I;//输入连接的数量
		int px, py, length;
		for (int i = 0; i < I; i++){
			cin >> px >> py >> length;//输入每个连接的信息
			int l_index = -1, r_index = -1;
			for (int j = 0; j < p; j++){
				if (py >= up[j] && py <= down[j]){
					
					if (x[j] + 1 == px) l_index = j;
					else if (x[j] == px + length) r_index = j;
					if (l_index != -1 && r_index != -1) break;
				}
			}
			pipe[l_index].push_back(make_pair(py,r_index));//对应的管道存储连接的长度以及另外一个管道的编号
			pipe[r_index].push_back(make_pair(py,l_index));
			link.insert(py);
		}
		cin >> target >> level;//输入目标管道的编号以及蜘蛛的位置
		target--;//在本代码中管道编号从0开始所以需要减一
		link.insert(level);//蜘蛛位置的y坐标也存入
		if (!(level >= up[target] && level <= down[target])){
			cout << "No Solution" << endl;
			continue;
		}
		pipe[target].push_back(make_pair(level,-2));
		for (int i = 0; i < p; i++){//对于每个管道,查看其长度范围内是否有连接,
			//如果有,就在此y值出将其自己与自己连接,便于后续的处理
			for (set<int>::iterator it = link.lower_bound(up[i]); 
				it != link.end()&&*it<down[i]; it++){
				pipe[i].push_back(make_pair(*it,i));
			}
			pipe[i].push_back(make_pair(up[i],-1));//假设管道的顶端是和编号为-1的管道相连接的,这样便于
			//进行后续的溢出判断
			pipe[i].sort();
			pipe[i].reverse();
		}
		answer = false;
		total = 0;
		solve();
		if (answer) cout << total << endl;
		else cout << "No Solution" << endl;
	}
	/*system("pause");*/
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值