CF1547E Air Conditioners

这道题看了几篇题解,也感到学到了一些知识


题意

先说题意

长度为 n 的一个一维的空间直线中,给定 k 个空调,同时给定其位置与设定的温度。问每一个格的温度分别是多少。

温度计算公式:
min ⁡ 1 ≤ j ≤ k ( t j + ∣ a j − i ∣ ) , \min_{1 \le j \le k}(t_j + |a_j - i|), 1jkmin(tj+aji),
就是所有空调设定的温度加上到这个点的距离的最小值就是这个点的温度

做法

首先第一个做法我觉得是适用性最高的,也同时能够对应好我前段时间简单学的多源BFS

把每个空调当做一个起点,同时加入到队列中去,用当前已知到的点去更新相邻的点。每个点的答案实际上可以根据左右两边的温度,来进行得到,通过公式我们知道,可以通过左右两个点此时的最小值加上增加的距离与1与当前的知道的这个点的答案进行比较取最小

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 3e5 + 10;
const int M = 1e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n, k;
int a[N];
int t[N];
int dis[N];

int main(){
    cin >> T;
    while(T--){
        memset(dis, 0x3f, sizeof(dis));
        priority_queue<PII, vector<PII>, greater<PII>> q;

        cin >> n >> k;

        for (int i = 1; i <= k; i++){
            cin >> a[i];
        }

        for (int i = 1; i <= k; i++){
            cin >> t[i];
            q.push({a[i], t[i]});
        }

        while(!q.empty()){
            auto t = q.top();
            q.pop();
            if(t.y < dis[t.x]){
                dis[t.x] = t.y;
                if(t.x + 1 <= n)
                    q.push({t.x + 1, t.y + 1});
                if(t.x - 1 >= 1)
                    q.push({t.x - 1, t.y + 1});
            }
        }

        for (int i = 1; i <= n; i++){
            cout << dis[i] << " ";
        }
        cout << Endl;
    }
}

思路来源:Messywind

https://blog.csdn.net/messywind/article/details/118653468?spm=1001.2014.3001.5501


根据上面的加粗的字,我们实际上可以就知道,每一个点的答案只是由左右两端确定的答案来进行更新的,要么被左边+1影响,要么被右边+1影响,这就构成了一个线性DP问题

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 3e5 + 10;
const int M = 1e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n, k;
int a[N];
int t[N];

int main(){
    cin >> T;
    while(T--){
        memset(t, 0x3f, sizeof(t));

        cin >> n >> k;

        for (int i = 1; i <= k; i++){
            scanf("%d", &a[i]);
        }

        for (int i = 1; i <= k; i++){
            int x;
            cin >> x;
            t[a[i]] = x;
        }

        for (int i = 1; i <= n; i++)
            t[i] = min(t[i - 1] + 1, t[i]);

        for (int i = n; i >= 1; i--)
            t[i] = min(t[i + 1] + 1, t[i]);

        for (int i = 1; i <= n; i++)
            cout << t[i] << " ";
        cout << Endl;
    }
}

思路来源:https://blog.csdn.net/weixin_50909982/article/details/118895522

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值