首页 > 其他分享 >P1514 [NOIP2010 提高组] 引水入城

P1514 [NOIP2010 提高组] 引水入城

时间:2023-10-02 15:55:32浏览次数:31  
标签:一个点 覆盖 NOIP2010 P1514 引水 复杂度 int bool define

link

搜索。

  1. 首先先用 \(dfs\) 判断一下对于每一个点来说对应的可以覆盖的 \(L,R\) . 假设题目一定存在一个解,所以一定会有该点覆盖的区间连续。设该区间为 \(L,R\) , 若不是每一个点均会被覆盖 ,那么题目不会存在任何一个解。

  2. 判断是否有解:跑一遍 \(dfs\) ,记录每一个点被 \(dfs\) 覆盖的情况,有多少个点未被覆盖那么就会有多少个点一定无解,此时如果无解点数 \(>\) 1 那么就必有题目无解的情况存在。

  3. 寻找最优解。贪心地做一遍线段覆盖即可。

但是这样时间复杂度瓶颈在于搜索部分,设对于任意点均有一种方案搜索到全局,那么此时的复杂度为 \(\Theta(n^2)\) 的,那么因为全局共有 \(n\) 个点,所以复杂度瓶颈为 \(\Theta(n^3)\) 。 然后可以考虑一下记忆化搜索。对每一个点取两个记忆:

\[[L,R] \]

然后可以考虑维护记忆化,转移的话就是 \(L_i=\min\{L_{j\in i}\} , R_i=\min\{R_{j \in i}\}\) 其中属于表示可以取到。

然后这样的话复杂度可以压缩到 \(O(n^2)\) ,相当小,这样就能够跑掉这道题了。

代码的话关注一下搜索的转移过程、线段覆盖的经过就行了。

#include <bits/stdc++.h>
#define ll long long
#define fir first
#define sec second
#define add push_back
const int N=4e3+5;
int h[N][N];
bool vis[N][N];
bool cf[N];

int left[N][N],right[N][N];

struct line{int l,r;}d[N];
const int dirx[]{0,0,1,0,-1};
const int diry[]{0,1,0,-1,0}; 
bool cmp(line ax,line ay){
	if(ax.l!=ay.l) return ax.l<ay.l;
	return ax.r > ay.r;
} 
int n,m;
bool judge(int x,int y,int px,int py){
	if(x<1 || x>n || y<1 || y>m) return false;
	if(h[px][py] <= h[x][y])return false;
	return true;
}

void dfs(int x,int y){
//	printf("dfs x=%d,y=%d\n",x,y);
	vis[x][y]=true;
	for(register int i=1;i<=4;++i){
		int nx=x+dirx[i],ny=y+diry[i];
		if(!judge(nx,ny,x,y)) continue;
		if(!vis[nx][ny]) dfs(nx,ny);
		left[x][y]= std::min(left[x][y],left[nx][ny]);
		right[x][y]= std::max(right[x][y],right[nx][ny]);
	}
//	printf("left = %d , right=%d;\n",left[x][y],right[x][y]);
}

void work(int u){
	dfs(1,u);
	int L=left[1][u],R=right[1][u];
	d[u]={L,R};
//	printf("L=%d,R=%d,u=%d\n",L,R,u);
	return;
}

void Init(void){
	memset(left,127,sizeof left);
	for(register int i=1;i<=m;++i)
		left[n][i]=i,right[n][i]=i;
}

int main(){
	scanf("%d%d",&n,&m);Init();
	
	for(register int i=1;i<=n;++i)
		for(register int j=1;j<=m;++j)
			scanf("%d",&h[i][j]);
	for(register int i=1;i<=m;++i)
		work(i);
	int cnt=0;
	for(register int i=1;i<=m;++i){
		if(!vis[n][i])++cnt;
	}
	if(cnt){
		printf("0\n%d\n",cnt);
		return 0;
	}
	std::sort(d+1,d+n+1,cmp);
	int index=1,num=1,ans=0;
	while(num<=m){
		int tmp=0;
		while(d[index].l<=num)
			tmp=std::max(tmp,d[index].r),
			++index;
		num=tmp+1;
		++ans;
	}
	puts("1");
	std::cout<<ans<<std::endl;
	return 0;
}

标签:一个点,覆盖,NOIP2010,P1514,引水,复杂度,int,bool,define
From: https://www.cnblogs.com/qxblog/p/P1514.html

相关文章

  • 引水入城
    [NOIP2010提高组]引水入城如果将每个上面的城市可以覆盖的城市看成可以供给若干个沙漠城市,那么这是一个最小覆盖问题,NPhard。但是,我们注意到如下的性质:假如一个上城市,不能覆盖中间那两个城市,那么任意一个上城市都不可覆盖它们,因为需要越过这个路线,那么既然走到这条路上,而之......
  • 「NOIP2010」机器翻译 题解
    前言附加任务这道题也是一个简单模拟题。传送门解析这道题就是一个简单的模拟题,简单来说就是如果内存里面没有这个单词(其实是一个数)的话就从外存入队,如果内存容量不够,出队即可。对了,每次查询时还要计数噢!代码话不多说上代码#include<bits/stdc++.h>usingnamespacestd......
  • [NOIP2010 提高组] 乌龟棋
    题目大意有四种卡片,它们分别可以让你前进1格,2格,3格和4格.在前进的道路上到达每个格子都会得到对应的积分.现在分别给出四种卡片的数量,求用完所有卡片能获得的最大积分和思路由于卡片只有4种,且每种的数量不超过20张,所以想到开四维dp,用dp[i][j][k][z]来表示用掉i张卡片4,j......
  • 算法学习记录:[NOIP2010]机器翻译
    题目链接https://ac.nowcoder.com/acm/contest/20960/1003记录:这道题我真的吃......
  • 第八届河南省赛 zzuoj 10409: D.引水工程 (最小生成树)
    10409:D.引水工程TimeLimit: 2Sec  MemoryLimit: 128MBSubmit: 111  Solved: 40[Submit][Status][WebBoard]Description南水北调工程是优化水资源配置、促进区域协调发展的基础性工程,是新中国成立以来投资额最大、涉及面最广的战略性工程,事关......
  • 23.4.15 NOIP2010提高游记
    第一次做提高,之前做的都是普及,还是感觉挺难的,心态有点裂开。1.机器翻译这题首先一看就是一道模拟题目,要注意的是字典的内存问题,在超内存以后要减1,直接上代码:-),时间复杂度O(n)1#include<bits/stdc++.h>2#pragmaGCCopzimize(3)3usingnamespacestd;4inlinelon......
  • P1540 [NOIP2010 提高组] 机器翻译
    P1540[NOIP2010提高组]机器翻译[NOIP2010提高组]机器翻译题目背景小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。题目描述这个翻译软件的......
  • 【NOIP2010】【codevs1069】关押罪犯(二分答案+二分图染色)
    problem将n个罪犯分别关押进2座监狱每2个罪犯之间有一个冲突值,当他们在同一监狱时就会爆发让爆发的冲突值(最大的那个)最小,求那个最小值solution考虑判定:是否存在一种分配方案......
  • 【NOIP2010】【Vijos1775】乌龟棋
    problemsolutioncodes#include<iostream>usingnamespacestd;intn,m,a[355],b[5],dp[40][40][40][40];intmain(){cin>>n>>m;for(inti=0;i<......
  • 【NOIP2010】【Luogu1540】机器翻译
    problemsolutioncodes//STL大法好#include<iostream>#include<set>#include<queue>usingnamespacestd;queue<int>q;set<int>s;intmain(){intm,n,an......