题目链接: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;
}