Air Conditioners

题目链接:https://codeforces.com/problemset/problem/1547/E

这个题意比较容易理解,就是让我们求每个空格的最低温度,这道题目可以用最短路解决,我们可以让每两个相邻的点的距离为1,然后建立一个虚拟源点,把每个装有空调的格子与虚拟源点连一条边,权值为空调的温度,最后直接跑一个dijkstra就可以求得答案,下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef pair<int,int> PII;
const int N=1e6;
int h[N],e[N],ne[N],w[N],idx,dist[N];
bool vis[N];
int p[N];
void add(int x,int y,int z)
{
	e[idx]=y;
	w[idx]=z;
	ne[idx]=h[x];
	h[x]=idx++;
}
void dijkstra()
{
	priority_queue<PII,vector<PII>,greater<PII> >q;
	q.push({0,0});
	dist[0]=0;
	while(q.size())
	{
		int begin=q.top().second;
		q.pop();
		if(vis[begin]) continue;
		vis[begin]=true;
		for(int i=h[begin];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dist[j]>dist[begin]+w[i])
			{
				dist[j]=dist[begin]+w[i];
				q.push({dist[j],j});
			}
		}
	}
	return ;
}
int main()
{
	int q;
	cin>>q;
	while(q--)
	{
		int n,k;
		scanf("%d%d",&n,&k);
		//建立虚拟源点h数组要从0开始赋值 
		for(int i=0;i<=n;i++)//用memset会超时(memset会对整个数组赋初值) 
		{
			h[i]=-1;
			dist[i]=0x3f3f3f3f;
			vis[i]=false;
		}
		idx=0;
		for(int i=1;i<=k;i++)
			scanf("%d",&p[i]);
		int t;
		for(int i=1;i<=k;i++)//建立虚拟远点与有空调的格子的有权边 
		{
			scanf("%d",&t);
			add(0,p[i],t);
		} 
		for(int i=1;i<n;i++)
		{
			add(i,i+1,1);
			add(i+1,i,1);
		}
		dijkstra();
		for(int i=1;i<=n;i++)
			printf("%d ",dist[i]);
		puts(""); 
	}
	return 0;
}

下面再分享一种做法:

我们考虑第i个格子的温度与哪些点的关系最密切,不难想到他与两边相邻的格子关系最为密切,要么就是由左边格子更新,要么就是由右边的格子更新,亦或者是自己本身的值,有了这个想法之后我们就可以用动态规划来做这道题目,动态转移方程就是t [ i ]=min( t [ i ] , t [ i -1 ]),和t [ i ]=min( t [ i ] , t [ i +1 ]),下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=1e6+10;
int dp[N],p[N];
int main()
{
	int q;
	cin>>q;
	while(q--)
	{
		int n,k;
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++)
			dp[i]=0x3f3f3f3f;
		for(int i=1;i<=k;i++)
			scanf("%d",&p[i]);
		int t;
		for(int i=1;i<=k;i++)
		{
			scanf("%d",&t);
			dp[p[i]]=t;
		}
		for(int i=2;i<=n;i++)//由左向右更新 
			dp[i]=min(dp[i-1]+1,dp[i]);
		for(int i=n-1;i>=1;i--)//由右向左更新 
			dp[i]=min(dp[i+1]+1,dp[i]);
		for(int i=1;i<=n;i++)
			printf("%d ",dp[i]);
		puts("");
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值