多源bfs

题目一

题意:

定义一种数为Lunlun数,这种数的任意相邻的位上的数 a i , a i + 1 a_i,a_{i+1} ai,ai+1都有 a b s ( a i − a i + 1 ) ≤ 1 abs(a_i - a_{i+1})\le1 abs(aiai+1)1,例:121001,现在给你一个正整数k让你求,从1开始的第k个Lunlun数

思路:

k的范围很小,所以可以用多源bfs,首先要先确定范围即第1e5个数最大可能是多少,或者知道我们需要bfs多少次可以得到第1e5个数,第一种方法可以直接推(我不会),所以我用第二种,先来看bfs:

for(int i = 0; i < 9; i++)
        qu.push(i + 1);
    while(qu.size()){
        ll t = qu.front();
        qu.pop();
        if(v.size() > k * 9)
            continue;
        v.push_back(t);
        ll temp2 = t % 10;
        if(temp2 == 9){
            qu.push(t * 10 + 9);
            qu.push(t * 10 + 8);
        }
        else if(temp2 == 0){
            qu.push(t * 10);
            qu.push(t * 10 + 1);
        }
        else{
            qu.push(t * 10 + temp2);
            qu.push(t * 10 + temp2 - 1);
            qu.push(t * 10 + temp2 + 1);
        }
    }

可以发现我取的bfs数是 k ∗ 9 k * 9 k9,多源bfs进行k次不一定能求出前k个数,因为他们的顺序不一,但是我们初始进行bfs的根是1~9个数,如果他们都bfs进行k次则一定包含前k个数。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
const ll maxn = 1e6 + 5;
ll a,b,c,d,k,n,m,t,num[maxn];
ll ans[maxn];
queue<ll> qu;
vector<ll> v;
set<ll> st;
void slove(){
    cin >> k;
    for(int i = 0; i < 9; i++)
        qu.push(i + 1);
    while(qu.size()){
        ll t = qu.front();
        qu.pop();
        if(v.size() > k * 9)
            continue;
        v.push_back(t);
        ll temp2 = t % 10;
        if(temp2 == 9){
            qu.push(t * 10 + 9);
            qu.push(t * 10 + 8);
        }
        else if(temp2 == 0){
            qu.push(t * 10);
            qu.push(t * 10 + 1);
        }
        else{
            qu.push(t * 10 + temp2);
            qu.push(t * 10 + temp2 - 1);
            qu.push(t * 10 + temp2 + 1);
        }
    }
}
int main()
{
    slove();
    sort(v.begin(),v.end());
    cout << v[k - 1] << endl;
    return 0;
}

题目二

题意:

给定n个互不相等整数 x 1 , x 2 . . . x n x_1,x_2...x_n x1,x2...xn,求另m个整数 y 1 , y 2 . . . y m y_1,y_2...y_m y1,y2...ym,满足:
1.任意 x ≠ y x\neq y x=y且任意y不相等
2.定义 d i = m i n ∣ y 1 − x j ∣ d_i = min|y_1 - x_j| di=miny1xj,使 ∑ i = 1 m d i \sum\limits_{i = 1}^{m}di i=1mdi最小

思路:

同样的思路我们可以先贪心,对于 x i x_i xi我们可以让 y = x i + 1 , y = x i − 1 y = x_i+1,y = x_i - 1 y=xi+1,y=xi1再来 x i − 2 , x i + 2... x_i - 2,x_i+ 2... xi2,xi+2...这样 d i d_i di就从1开始一点一点大也就让 ∑ i = 1 m d i \sum\limits_{i = 1}^{m}di i=1mdi最小了

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
const ll maxn = 1e6 + 5;
ll a,b,c,d,k,n,m,t,num[maxn],sum;
typedef pair<int,int> PL;
set<int> st;
vector<int> v;
queue<PL> qu;
int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> num[i];
    for(int i = 1; i <= n; i++){
        st.insert(num[i]);
        qu.push({num[i],num[i] - 1}),qu.push({num[i],num[i] + 1});
    }
    while(qu.size() && m > 0){
        PL t = qu.front();
        qu.pop();
        if(st.find(t.second) != st.end())
            continue;
        st.insert(t.second),sum += abs(t.first - t.second);
        m--,v.push_back(t.second);
        qu.push({t.first,t.second - 1});
        qu.push({t.first,t.second + 1});
    }
    cout << sum << endl;
    for(int i = 0; i < v.size(); i++)
        cout << v[i] << " ";
    return 0;
}
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页