首页 > 其他分享 >20221115_T4B_折半搜索双指针

20221115_T4B_折半搜索双指针

时间:2022-11-15 15:24:46浏览次数:48  
标签:折半 int 20221115 vpii leq read T4B inf size

题意

市面上共有 \(n\) 张门票,方便起见,我们把它们从 \(1\) 至 \(n\) 编号。其中,\(i\) 号门票对应的场次为第 \(b_i,1\leq b_i\leq k)\)场,价格为 \(c_i\) 元,且座位的排数为 \(p_i\)。
现在,Yazid 共有 \(m\) 元的总预算,他打算在不超出预算的情况下,购买到 \(k\) 张排数总和最小的门票。
请你帮帮 Yazid 挑选合适的门票,方便起见,你只需输出这个最小总排数即可。

数据范围 \(n\leq 100, k \leq 12, m, c_i \leq {10}^9\)

题解

赛时得分 50/100 (打的暴力,挂了 10 分)

这明显是一个不可 dp 的背包。我们考虑如何优化搜索。

我们可以将两个背包合并起来,我们尝试将 \(12\) 个背包合并成 \(2\) 个。

这两个枚举中间所有东西,按照 \(v\) 排序,因为排序之后 \(i\) 从小到大扫描 \(v\) 满足条件的从大到小。所以复杂度是集合大小的。

所以总时间复杂度是一个集合大小的,应该是 \(\mathcal{O}(\Big(\frac{n}{k}\Big)^k)\) 的,差不多为 \(8^6\) 可以通过本题。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T>inline void read(T& t){t=0; register char ch=getchar(); register int fflag=1;while(!('0'<=ch&&ch<='9')) {if(ch=='-') fflag=-1;ch=getchar();}while(('0'<=ch&&ch<='9')){t=t*10+ch-'0'; ch=getchar();} t*=fflag;}
template <typename T,typename... Args> inline void read(T& t, Args&... args) {read(t);read(args...);}
const int N = 1e5 + 10, inf = 0x3f3f3f3f3f3f3f3f;

typedef pair<int, int> pii;
typedef vector<pii> vpii;

vpii a, b;
vpii obj[13];
int T, n, m, k;

vpii trans(vpii x, vpii y) {
    vpii res;
    res.clear();
    for(auto [w1, v1] : x) 
        for(auto [w2, v2] : y) 
            if(w1 + w2 <= m) res.push_back(make_pair(w1 + w2, v1 + v2));
    return res;
}

signed main() {
    freopen("ticket.in", "r", stdin);
    freopen("ticket.out", "w", stdout);
    read(T);
    while(T--) {
        read(n, m, k);
        a.clear(), b.clear();
        for(int i = 1; i <= k; ++i) obj[i].clear();
        for(int i = 1; i <= n; ++i) {
            int bl, w, v;
            read(bl, w, v);
            obj[bl].push_back(make_pair(w, v));
        }
        a.push_back(make_pair(0, 0));
        b.push_back(make_pair(0, 0));
        for(int i = 1; i <= k; ++i) {
            if(a.size() > b.size()) swap(a, b);
            a = trans(a, obj[i]);
        }
        sort(a.begin(), a.end());
        sort(b.begin(), b.end());
        if(a.size() == 0 || b.size() == 0) {
            puts("No solution");
            continue;
        }
        int minn = inf, ans = inf;
        for(int i = a.size() - 1, j = 0; i >= 0; --i) {
            while(j < b.size() && b[j].first + a[i].first <= m) {
                minn = min(minn, b[j].second);
                ++j;
            }
            if(j == 0) continue;
            ans = min(ans, minn + a[i].second);
        }
        if(ans >= inf) {
            puts("No solution");
            continue;
        }
        cout << ans << endl;
    }
    return 0;
}

标签:折半,int,20221115,vpii,leq,read,T4B,inf,size
From: https://www.cnblogs.com/Mercury-City/p/16892498.html

相关文章

  • test20221115 打铁记
    总述\(53+20+20+0=93\),班上\(rk9\),太菜了。考场T1特殊性质+暴力(可是没有打满),T2特殊性质,T3暴力。费时\(40\)分钟,剩下的时间写正解(没写出来)+摆烂。感谢cy同志让......
  • 20221115_T3A+_贪心二分
    题意你在和Yazid做游戏。Yazid给了你一棵\(n\)个节点的树,并让你删除这棵树上的恰好\(k\)条边,使得整棵树被分成\(k+1\)个连通块。你觉得太简单了,随便删k条边......
  • GL-Facing a challenge 20221115
    Time2022.11.14Monday23:30-00:15TopicFacingachallengeWhatisthehardestthingyou'veeverhadtodo?howdidyoumanagetoovvercometheobstaclesin......
  • 20221114_T4B_树形dp换根dp
    题意太冗长了传一张图片自己看吧。题解赛时得分15/100/100赛时写了\(A=0\)的乱搞,没写对但是拿了15pts。首先这个函数是一个增函数,对于power和score两个指标......
  • 20221114_T4B_拓扑排序贪心
    题意L国正在举行各种会议,但是可怜的是L国只有一个主持人,每场会议的开始主持人都必须去主持会议,使会议得以开始,在会议开始后主持人可以离开。 主持人不会分身,他在一个时刻......
  • 洛谷 P3067 [USACO12OPEN]Balanced Cow Subsets G 折半搜索
    题目https://www.luogu.com.cn/problem/P3067思路考虑折半搜索,第一个dfs对[1,n/2]的数进行分组,+代表第一组,-代表第二组,并计算两组总和的情况方案数\(a_i\)。第二个dfs......
  • DS | 折半查找二叉判定树的画法
    以下给出我在学习中总结的一种比较简便的构造折半二叉判定树的思路以及方法:思路分析:在计算\(mid\)值时,使用的时\(mid=(low+high)/2\)。这里由于\(mid\)为int类......
  • 洛谷 P5194 [USACO05DEC]Scales S 折半搜索
    题目https://www.luogu.com.cn/problem/P5194思路\(n\leq1000\)的范围很吓人,但是按照【每个砝码的质量至少等于前面两个砝码的质量的和】的规则,打表可知n在50时总重量......
  • 折半查找
    #include<map>#include<stdio.h>#include<iostream>usingnamespacestd;longlongbox[50];longlongpos[50];intmain(){longlongn,m;cin>>n>......