bfs|[bzoj4828] [Hnoi2017]大佬

题目描述
人们总是难免会碰到大佬。他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语。你作为一个OIER,面对这样的事情非常不开心,于是发表了对大佬不敬的言论。大佬便对你开始了报复,你也不示弱,扬言要打倒大佬。
现在给你讲解一下什么是大佬,大佬除了是神犇以外,还有着强大的自信心,自信程度可以被量化为一个正整数C(1<=C<=10^8),想要打倒一个大佬的唯一方法是摧毁Ta的自信心,也就是让大佬的自信值等于0(恰好等于0,不能小于0)。由于你被大佬盯上了,所以你需要准备好n(1<=n<=100)天来和大佬较量,因为这n天大佬只会嘲讽你动摇你的自信,到了第n+1天,如果大佬发现你还不服,就会直接虐到你服,这样你就丧失斗争的能力了。
你的自信程度同样也可以被量化,我们用mc (1 <= mc <= 100)来表示你的自信值上限。在第i天(i>=1),大佬会对你发动一次嘲讽,使你的自信值减小a[i],如果这个时刻你的自信值小于0了,那么你就丧失斗争能力,也就失败了(特别注意你的自信值为0的时候还可以继续和大佬斗争)。在这一天,大佬对你发动嘲讽之后,如果你的自信值仍大于等于0,你能且仅能选择如下的行为之一:
1. 还一句嘴,大佬会有点惊讶,导致大佬的自信值C减小1。
2. 做一天的水题,使得自己的当前自信值增加w[i], 并将新自信值和自信值上限mc比较,若新自信值大于mc,则新自信值更新为mc。例如,mc=50,当前自信值为40,若w[i]=5,则新自信值为45,若w[i]=11,则新自信值为50。
3. 让自己的等级值L加1。
4. 让自己的讽刺能力F乘以自己当前等级L,使讽刺能力F更新为F*L。
5. 怼大佬,让大佬的自信值C减小F。并在怼完大佬之后,你自己的等级L自动降为0,讽刺能力F降为1。由于怼大佬比较掉人品,所以这个操作只能做不超过2次。
特别注意的是,在任何时候,你不能让大佬的自信值为负,因为自信值为负,对大佬来说意味着屈辱,而大佬但凡遇到屈辱就会进化为更厉害的大佬直接虐飞你。在第1天,在你被攻击之前,你的自信是满的(初始自信值等于自信值上限mc),你的讽刺能力F是1,等级是0。
现在由于你得罪了大佬,你需要准备和大佬正面杠,你知道世界上一共有m(1<=m<= 20)个大佬,他们的嘲讽时间都是n天,而且第i天的嘲讽值都是a[i]。不管和哪个大佬较量,你在第i天做水题的自信回涨都是w[i]。这m个大佬中只会有一个来和你较量(n天里都是这个大佬和你较量),但是作为你,你需要知道对于任意一个大佬,你是否能摧毁他的自信,也就是让他的自信值恰好等于0。和某一个大佬较量时,其他大佬不会插手。
分析
首先可以设f[i][j]表示前i天,自信值为j,最多能不刷题多少天。不刷题的时候是用来做其它操作的。这样就可以算出最多动多少天,设它是D天。
【bfs|[bzoj4828] [Hnoi2017]大佬】接着从最多进行两次怼操作入手。设d[f][l]表示达到能力f,等级l,所需的最少天数。保证d[f][l]<D。可以发现它的状态数不多。
然后假设一位dalao的体力为C,那么现在我进行两次怼操作,设它们所需天数、伤害分别是d1,f1、d2,f2。那么满足D-d1-d2≥C-f1-f2时,就是有解的。然而状态数不多,所以可以用个two pointers扫一遍。

#include #include #include using namespace std; const int N=105,M=11147953,inf=1e8; typedef long long LL; int n,m,mc,h[M],tot,a[N],w[N],D,d[M/2][3],F[M],L[M],mi; int f[N][N]; struct data { int f,d; }A[M/2]; bool cmp(data a,data b) { return a.f0 && (F[k]!=f || L[k]!=l); ) { k++; if (k==M) k-=M; } return k; }int main() { scanf("%d%d%d",&n,&m,&mc); for (int i=1; i<=n; i++) scanf("%d",&a[i]); for (int i=1; i<=n; i++) scanf("%d",&w[i]); for (int j=0; j<=n; j++) for (int i=0; i<=101; i++) f[j][i]=-n; f[0][mc]=0; for (int i=1; i<=n; i++) { for (int j=a[i]; j<=mc; j++) { f[i][j-a[i]]=max(f[i][j-a[i]],f[i-1][j]+1); int t=min(mc,j-a[i]+w[i]); f[i][t]=max(f[i][t],f[i-1][j]); } } for (int i=0; i<=n; i++) for (int j=0; j<=mc; j++) D=max(D,f[i][j]); d[1][0]=1; int id=gethash(1,0); h[id]=1; F[id]=1; tot=1; for (int i=1; i<=tot; i++) { int f=d[i][0],l=d[i][1],day=d[i][2],id; if (day>=D-1) break; if (l>0 && inf/lj && A[i].f+A[j].f<=c; j++) if (A[j].d-A[j].f

    推荐阅读