日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客网 【每日一题】6月11日题目精讲 背包

發(fā)布時(shí)間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客网 【每日一题】6月11日题目精讲 背包 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鏈接:

文章目錄

    • 題目描述
    • 題解:
    • 代碼:

題目描述

Applese有1個(gè)容量為v的背包,有n個(gè)物品,每一個(gè)物品有一個(gè)價(jià)值ai,以及一個(gè)大小bi
然后他對(duì)此提出了自己的疑問,如果我不要裝的物品裝的價(jià)值最大,只是一定需要裝m個(gè)物品,要使得求出來的物品價(jià)值的中位數(shù)最大
Applese覺得這個(gè)題依然太菜,于是他把這個(gè)問題丟給了你 當(dāng)物品數(shù)量為偶數(shù)時(shí),中位數(shù)即中間兩個(gè)物品的價(jià)值的平均值

輸入描述:

第一行三個(gè)數(shù)v, n, m,分別代表背包容量,物品數(shù)量以及需要取出的物品數(shù)量 接下來n行,每行兩個(gè)數(shù)ai,bi,分別代表物品價(jià)值以及大小 n
≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v

輸出描述:

僅一行,代表最大的中位數(shù)

示例1
輸入

20 5 3 3 5 5 6 8 7 10 6 15 10

輸出

8

題解:

第一反應(yīng)感覺是二分
m有奇數(shù)偶數(shù)兩種情況
當(dāng)m是奇數(shù)時(shí),左右分別取m/2個(gè),最中間的就是我們要的答案
當(dāng)m為偶數(shù)時(shí),左邊取m/2-1個(gè),右邊取m/2個(gè),中位數(shù)為兩個(gè)數(shù),就是當(dāng)前第i個(gè)數(shù)和右邊第一個(gè)數(shù)(因?yàn)槲覀兠杜e時(shí)只能選定一個(gè),所以就通過選定第i個(gè)把第i+1也確定)
接下來詳細(xì)講講過程
x[i]表示物品最小體積的前綴和
y[]表示物品最小體積的后綴和

對(duì)于每一個(gè)位置,我們枚舉左右兩邊體積最小的m/2個(gè)數(shù),(因?yàn)樽笥覂蛇咉w積越小,給中間留的越多)
我們可以用優(yōu)先隊(duì)列,從小到大依次放入,當(dāng)背包容量不夠時(shí),去掉最大值,依次這樣操作,留到最后的就是合理值

當(dāng)求奇數(shù)時(shí),枚舉每個(gè)位置,如果左右兩邊m/2個(gè)和中間的大小符合條件,則說明滿足條件。取最大的中間值

當(dāng)求偶數(shù)時(shí),最終答案是兩個(gè)數(shù)的平均值,我們枚舉這兩個(gè)中左邊的數(shù),左邊取m/2-1個(gè)右邊取m/2個(gè)。我們的序列是經(jīng)過排序的,右邊的第一個(gè)數(shù)取的越靠右
中位數(shù)就越大,但是越靠右他的物品總大小一定不會(huì)減少中位數(shù)就越大,但是越靠右他的物品總大小一定不會(huì)減少
可以發(fā)現(xiàn),右邊選取物品的總大小是一個(gè)遞增的可以發(fā)現(xiàn),右邊選取物品的總大小是一個(gè)遞增的
與此同時(shí),他的價(jià)值也是遞增的,那么可以發(fā)現(xiàn)與此同時(shí),他的價(jià)值也是遞增的,那么可以發(fā)現(xiàn)應(yīng)該在大小符合的條件下盡量往右選,這就是明顯的二分啊應(yīng)該在大小符合的條件下盡量往右選,這就是明顯的二分,直接二分右邊第一個(gè)的位置找到盡量靠右的合法位置即可
題解借鑒

代碼:

代碼是有問題的,但是我看了一陣子也沒找出來。。。

#include<bits/stdc++.h> const int maxn= 1e5+2; typedef long long ll; using namespace std; struct node{ll a,b,id; }w[maxn]; ll x[maxn],y[maxn]; //x表示前i個(gè)數(shù)(含第i個(gè))取m/2個(gè)物品其大小的和的最小值 //y表示后i個(gè)數(shù)(含第i個(gè))取m/2個(gè)物品其大小的和的最小值 bool cmp1(node a1,node b1) {return a1.a<b1.a;//按照 價(jià)值排序 } priority_queue<int>q; long long int v,n,m; //v n m ll solve1(){ll sum=0;for(int i=m+1;i<=n-m;i++){if(x[i-1]+y[i+1]+w[i].b<=v)sum=w[i].a;//枚舉中間值,再上左右兩邊,看看有沒有超過背包容量 return sum;} } ll solve2(){ll sum=0;for(int i=m;i<=n-m;i++){int l=i+1;int r=n-m+1;while(l<=r){//偶數(shù)有兩個(gè)中位數(shù),先確定一個(gè),然后二分另外一個(gè) int mid=(r+l)>>1;if(x[i-1]+y[mid]+w[i].b<=v)l=mid+1;//如果沒超過背包的體積,說明中間值還可以更大 else r=mid-1;//否則更小 }if(r>i)sum=max(sum,w[i].a+w[r].a);//中間兩個(gè)值和的最大值 }return sum/2; } int main() {cin>>v>>n>>m;for(int i=1;i<=n;i++){cin>>w[i].a>>w[i].b;}sort(w+1,w+1+n,cmp1);int z=m&1;m>>=1;for(int i=1;i<=n;i++){q.push(w[i].b);x[i]=x[i-1]+w[i].b;if(q.size()>m-1+z){x[i]-=q.top();q.pop();}}while(!q.empty())q.pop();for(int i=n;i;i--){q.push(w[i].b);y[i]=y[i+1]+w[i].b;if(q.size()>m){y[i]-=q.top();q.pop();}}if(z){cout<<solve1();}else {cout<<solve2();}return 0; }

總結(jié)

以上是生活随笔為你收集整理的牛客网 【每日一题】6月11日题目精讲 背包的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。