洛谷P1650:田忌赛马(贪心)
解析
其實并不簡單的一道題。
是劉汝佳老師的例題,搜到之后按照講的策略寫了一發。
(由于這個策略并不完全正確,就不展開講了)
好啊!
可是感覺講的策略特別對,為什么呢?
原因在于,課上的策略是建立于 比賽非贏即輸的前提下,而本題存在平局。
當最小值相等時,這個貪心直接讓最小值去找最大值送死或者讓兩個最小值打平都不一定是最優的。
分別的hack數據:
(以下設 a1...na_{1...n}a1...n? 是田忌的馬,b1...nb_{1...n}b1...n? 是齊王的馬,按升序排列,x?yx-yx?y 表示 x,yx,yx,y 對局)
那么怎么辦呢?
注意到,我們可以用類似的套路對最大值進行處理,那么我們現在的問題就只在于如何處理最大值和最小值都相等的時候了,即 a1=b1,an=bna_1=b_1,a_n=b_na1?=b1?,an?=bn?。
在 a1=b1=an=bna_1=b_1=a_n=b_na1?=b1?=an?=bn? 的時候怎么選結果都是一樣的,因此我們只討論 a1<an,b1<bna_1<a_n,b_1<b_na1?<an?,b1?<bn? 的情況。
一個樸素的想法還是用最小值霍霍對方的最大值 (a1?bna_1-b_na1??bn?),而此時這個做法是對的,以下給出證明。
假設最優解并非如此,就有:a1?bj,ai?bna_1-b_j,a_i-b_na1??bj?,ai??bn?,此時的價值優于 a1?bn,ai?bja_1-b_n,a_i-b_ja1??bn?,ai??bj?
接下來分情況討論:
綜上所述,使 a1?bna_1-b_na1??bn? 始終是不劣的。
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=2e6+100; const int M=1e6+100; const int mod=1e9; int n; int a[N],b[N],pl,ans;signed main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=read();for(int i=1;i<=n;i++) a[i]=read();for(int i=1;i<=n;i++) b[i]=read();sort(a+1,a+1+n);sort(b+1,b+1+n);int al=1,ar=n,bl=1,br=n;while(al<=ar){if(a[al]<b[bl]){++al;--br;ans-=200;}else if(a[al]>b[bl]){++al;++bl;ans+=200;}else if(a[ar]>b[br]){--ar;--br;ans+=200;}else if(a[ar]<b[br]){++al;--br;ans-=200;}else{if(a[al]<b[br]) ans-=200;++al;--br;}}printf("%d\n",ans);return 0; } /* 3 2 2 2 2 2 3 */總結
以上是生活随笔為你收集整理的洛谷P1650:田忌赛马(贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开学季必备装备:桌搭蓝牙音箱就该这么选
- 下一篇: 抖音、快手、火山、B站等短视频怎么批量去