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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HZOJ 赤(CF739E Gosha is hunting)

發布時間:2025/4/16 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HZOJ 赤(CF739E Gosha is hunting) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本來沒有打算寫題解的,時間有點緊。但是這個wqs二分看了好久才明白還是寫點東西吧。

題解就直接粘dg的了:

(red)

本題來自codeforces 739E,加大了數據范圍.

首先對一只貓不會扔兩個及以上數量的同種食物。最優方案一定食物用完.

每只貓對期望的貢獻可以根據期望的線性性分開算的,不投喂,這只貓貢獻為0;

只喂干脆面,貢獻為pi;只喂豆干,貢獻為qi;兩種都喂,貢獻為pi+qi-pi*qi

算法1

對于每只貓,只有4種情況,所以我們大力枚舉一下,單組數據O(4^n),可以通過第1個測試點,期望得分10分。

算法2

對于第2個測試點,有剛好等于貓數的豆干或干脆面,那么我們把等于貓數的食品一只貓喂一個,考慮每只貓多喂另一種食品后能新得到的貢獻,例如,第i只貓已經喂了一個豆干,再喂一包干脆面對期望的貢獻為(1-qi)*pi,可以認為不喜歡豆干時干脆面才會新產生貢獻。我們排個序就好了,單組數據O(n+nlogn),結合算法1,期望得分20.

算法3

考慮DP,定義f[i][j][k]為前i只貓投喂j包干脆面和k包豆干時得到的最大期望貓數,轉移時考慮第i只貓如何投喂,復雜度O(nab),可以通過1,2,3,4號測試點,期望得分40分。

算法4

注意到第5個測試點的ab都相當大,那么沒有被投喂的貓就會相對較少,我們考慮對沒有被投喂的貓進行DP。不妨先給所有的貓都同時投喂兩種食品,然后再收回n-a包豆干和n-b包干脆面,最小化期望貓數的損失即可。DP和算法3類似,時間復雜度O(n(n-a)(n-b))結合算法3,期望得分50分。

67個測試點是為復雜度較優的算法準備的。

算法5

考慮網絡流。給一只貓分配一包干脆面可以得到pi的收益,給一只貓分配一包豆干可以得到qi的收益,但同時分配這兩種食品將損失pi*qi的收益.如果不考慮pi*qi的損失,有一個很明顯的費用流建圖:建兩個點表示豆干和干脆面,從原點向這兩個點分別連費用為0,流量等于對應食品數目的邊,從干脆面向每只貓連流量為1,費用為pi的邊,從豆干向每只貓連流量為1,費用為qi的邊,從每只貓向匯點連流量為2,費用為0的邊。那么pi*qi的損失應當可以加到這個比較簡單的模型的某一條邊上。聰明的你一定想到了,我們把從貓連向匯點的邊拆成兩條,流量均為1,但一條費用為0,一條費用為-pi*qi,這樣跑出來就是對的。

時間復雜度O(費用流).

期望得分70

算法6:

cf官方題解的方法,用數據結構維護貪心。可見這個題并沒有考網絡流

期望得分70

算法7

這是一種被稱作Wqs二分(wqs=王欽石)的黑科技。熟悉wqs二分的選手可以直接去看算法8.

假設看這里的選手沒有聽說過wqs二分.

考慮如何優化算法3O(n^3)DP.

我們首先不考慮b的限制,假設豆干可以任意使用,定義f[i][j]表示前i只貓使用j包干脆面和若干包豆干得到的最大收益直接這么DPn只貓都用豆干,可能會超出b的限制。

為了減少豆干的使用,我們可以假定使用一個豆干需要額外付出cost的代價(也就是在轉移的時候如果一只貓用了豆干,對期望值的貢獻要減去cost).DP的時候,求解出f[i][j]最大值,記錄最優方案中豆干使用的數目x,那么此時真實的期望f[i][j]最優值加上x*cost,這個結果必然也是用了x 豆干時能夠得到的最優結果.

但是,如果我們隨便假定一個cost去跑DP,得到方案并不一定所有豆干都用完,我們需要一個能把所有豆干都用完的cost的值.

顯然豆干使用量隨著cost變化是單調變化的,我們可以二分cost的數值.

時間復雜度O(n2logn)

期望得分70.

算法8(滿分算法)

我們還可以做到O(nlog2n),具體做法算法7的基礎上,wqs二分套wqs二分,把DP再減少一維。假設用豆干cost1的額外花費,干脆面有cost2額外花費.f[i]表示i只貓的最大收益.然后外層二分cost1內層二分cost2.

標程理解一下吧.

這個做法當然不是lrd想出來的啦.

出處:http://codeforces.com/blog/entry/49691

出題人的預測:NOIP水平的選手拿到本題的前50分就不錯.50應當還是有區分度的.水平稍高的選手可能打出一種復雜度較好的算法拿到70.滿分做法應當是相當難想到的.

1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #define int long long 6 #define MP(a,b) make_pair(a,b) 7 using namespace std; 8 const double esp=1e-10; 9 int n,a,b; 10 double p[100010],q[100010]; 11 struct zt 12 { 13 int x,y;double val; 14 void clear(){x=val=y=0;} 15 friend bool operator < (zt a,zt b) 16 { 17 if(a.val!=b.val)return a.val<b.val; 18 if(a.y!=b.y)return a.y>b.y; 19 return a.x>b.x; 20 } 21 }f[2]; 22 inline int read(); 23 signed main()//清空 24 { 25 while(cin>>n>>a>>b) 26 { 27 for(int i=1;i<=n;i++)scanf("%lf",&p[i]); 28 for(int i=1;i<=n;i++)scanf("%lf",&q[i]); 29 30 double L=0,R=1,cost1,ans=0,cost2; 31 while(R-L>=esp) 32 { 33 cost1=(L+R)/2;f[0].clear(),f[1].clear(); 34 double l=0,r=1;zt res;res.clear(); 35 while(r-l>=esp) 36 { 37 cost2=(l+r)/2;f[0].clear();f[1].clear(); 38 for(int i=1;i<=n;i++) 39 { 40 int now=i%2,pre=(i-1)%2; 41 f[now]=f[pre];double tv; 42 tv=f[pre].val+p[i]-cost1; 43 if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x+1,f[pre].y,tv}; 44 tv=f[pre].val+q[i]-cost2; 45 if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x,f[pre].y+1,tv}; 46 tv=f[pre].val+p[i]+q[i]-p[i]*q[i]-cost1-cost2; 47 if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x+1,f[pre].y+1,tv}; 48 } 49 int now=n%2; 50 if(f[now].y<=b)res=max(res,f[now]),r=cost2; 51 else l=cost2; 52 if(f[now].y==b){res=f[now];break;} 53 } 54 if(res.x<=a)ans=max(ans,res.val+res.x*cost1+res.y*cost2),R=cost1; 55 else L=cost1; 56 if(res.x==a)break; 57 } 58 printf("%0.5lf\n",f[n%2].val+a*cost1+b*cost2); 59 // printf("%0.5lf\n",ans); 60 } 61 } 62 inline int read() 63 { 64 int s=0,f=1;char a=getchar(); 65 while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();} 66 while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} 67 return s*f; 68 } View Code

dg的題解是真的詳細,照著打應該不是很難。

但是關于wqs二分有一個細節好久才弄明白。

就是最后答案為什么是‘f[n%2].val+a*cost1+b*cost2’而不是f[n%2].val+f[n%2].x*cost1+f[n%2].y*cost2',明明只用了x包干脆面和y個豆干為什么要加上a,b的補充權值?

于是我在代碼后面加了這個:‘if(f[n%2].x!=a||f[n%2].y!=b)puts("!!!!!!!!!!!1");’

最后求出來的x,y和a,b并不一樣。但是顯然都用完是最優的。問題在于可能并不存在一組cost1,cost2使得dp出來正好是都用完的,比如 所有的貓的p都相等而a<n,那么二分出來x要么是0要么是n。這種時候繼續二分找到一個最貼近的補充權值cost1使得a*cost1最優。

大概就這些吧。

?

?

?

轉載于:https://www.cnblogs.com/Al-Ca/p/11479593.html

總結

以上是生活随笔為你收集整理的HZOJ 赤(CF739E Gosha is hunting)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。