The Strongest Build(bfs+优先队列)

题目链接
题意:
\(n\)个从小到大的数组,从每个数组中选取一个下标构成长度为\(n\)的序列,但有\(m\)个序列被禁止,求不属于禁止序列且下标对应元素和最大的序列。

思路:
首先得到元素和最大的序列,即为每个数组最后一个元素构成的序列,若该序列不属于禁止序列,则该系列为所求序列。否则由该序列进行\(bfs\)搜索,替换其中某个元素,求得其次大值序列,若该序列没有被访问,则将值和序列放入优先队列。每次从优先队列中取出值最大的序列,若序列不在禁止序列中,则输出该序列,否则继续进行\(bfs\)搜索。只有\(m\)个禁止序列,且\(n<=10\),所以最多进行\(m*10\)次搜索就可得到答案。用\(hash\)表记录禁止序列和访问过的序列(也可用\(map、set\)记录,\(hash\)表取进制\(p=131\)\(wa\)第41个点,可取\(p=13331\))。

code:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#include <unordered_map>

#define fi first
#define se second
#define pb push_back
#define endl "\n"
#define debug(x) cout << #x << ":" << x << endl;
#define bug cout << "********" << endl;
#define all(x) x.begin(), x.end()
#define lowbit(x) x & -x
#define fin(x) freopen(x, "r", stdin)
#define fout(x) freopen(x, "w", stdout)
#define ull unsigned long long
#define ll long long 

const double eps = 1e-15;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const int mod =  998244353;
const int maxn = 2e5 + 10;

using namespace std;

#define piv pair<int, vector<int>>
int s[12], n, m, w[12][maxn];
priority_queue<piv> q;
unordered_map<ull, bool> mp, ban;

ull get(vector<int> &v){
    ull ret = 0;
    for(auto i : v)ret = ret * 13331 + i;
    return ret;
}

int main(){
    piv ans; int ret = 0;
    vector<int> k;
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++){
        scanf("%d", &s[i]);
        for(int j = 1, a; j <= s[i]; j ++){
            scanf("%d", &w[i][j]);
        }
        ret += w[i][s[i]], k.pb(s[i]);
    }
    q.push(make_pair(ret, k));

    scanf("%d", &m);
    for(int i = 1; i <= m; i ++){ 
        k.clear();   
        for(int j = 1, a; j <= n; j ++){
            scanf("%d", &a);
            k.pb(a);
        }
        ban[get(k)] = 1;
    }

    while(q.size()){
        piv p;
        p = q.top(); q.pop();
        if(!ban[get(p.se)]){ans = p; break;}
        for(int i = 0; i < n; i ++){
            if(p.se[i] > 1){
                piv p1 = p;
                p1.fi += w[i + 1][p1.se[i] - 1] - w[i + 1][p1.se[i]];
                p1.se[i] -= 1;
                if(!mp[get(p1.se)])mp[get(p1.se)] = 1, q.push(p1);
            }
        }
    }

    for(int i = 0; i < n; i ++)printf("%d ", ans.se[i]);
    return 0;
}
posted @ 2021-09-26 18:44  lniiwuw  阅读(59)  评论(0)    收藏  举报