LOJ #2021. 「AHOI / HNOI2017」大佬(DP)

题目
感觉这题和劈配差不多恶心人的脑筋。

能造成的伤害只和你有几天来打伤害有关,至于是那几天,这不重要。
所以我们就可以通过 d p dp 求出你最多能苟多少天来打伤害(注意即使你苟最多天的方案会导致你最后丧失斗争能力你也要接受)。
然后BFS(搜)出苟 i i 天用一次怼大佬能打出的伤害 v v 的所有方案 ( v , i ) (v,i)
注意那个 i i 要取最小的 i i
然后对于每个大佬,我们对于需要找出两个方案 ( a , b ) , ( c , d ) (a,b),(c,d) 使得 D b d C a c & C a c 0 D-b-d\geq C-a-c \& C-a-c\geq 0
简单双指针扫一遍即可。

A C   C o d e \mathrm {AC \ Code}

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define pii pair<int,int>
#define mp make_pair
using namespace std;

int n,m,mc,a[105],w[105],dp[2][105];
map<int,int>mAp[105];
map<int,int>ar;
pii c[1000000];

int main(){
	scanf("%d%d%d",&n,&m,&mc);
	rep(i,1,n) scanf("%d",&a[i]);
	rep(i,1,n) scanf("%d",&w[i]);
	int now=1,pre=0;
	memset(dp,-0x3f,sizeof dp);dp[now][mc]=0;
	int Day = 0;
	rep(i,1,n){
		swap(now,pre);
		memset(dp[now],-0x3f,sizeof dp[now]);
		rep(j,a[i],mc) 
			if(dp[pre][j]>=0){
				dp[now][j-a[i]]=max(dp[now][j-a[i]],dp[pre][j]+1),
				dp[now][min(mc,j-a[i]+w[i])]=max(dp[now][min(mc,j-a[i]+w[i])],dp[pre][j]);
			}
		Day = max(Day , *max_element(dp[now],dp[now]+mc+1));
	}
	queue<pii>q;
	q.push(mp(0,1));
	mAp[0][1] = 1;ar[0]=0;
	for(int u,v;!q.empty();){
		u=q.front().first,v=q.front().second,q.pop();
		if(ar.count(v) == 0) ar[v] = 0x3f3f3f3f;
		ar[v]=min(ar[v],mAp[u][v]);
		if(mAp[u][v] >= Day) continue;
		if(1ll*u*v<=1e8 && !mAp[u].count(u*v)) mAp[u][u*v] = mAp[u][v] + 1 , q.push(mp(u,u*v));
		if(!mAp[u+1].count(v)) mAp[u+1][v] = mAp[u][v] + 1 , q.push(mp(u+1,v));
	}
	int tot = 0;
	for(pii u:ar)
		c[tot++] = u;
	for(int C;m--;){
		scanf("%d",&C);
		int j=tot-1;
		bool flg = 0;
		rep(i,0,tot-1){
			for(;j>=i && c[i].first+c[j].first > C;j--);
			if(j>=0 && C - c[i].first - c[j].first>=0 && Day - c[i].second - c[j].second >= C - c[i].first - c[j].first){
				flg = 1;
				break;
			}
		}
		if(flg) puts("1");
		else puts("0");
	}
}

发布了627 篇原创文章 · 获赞 91 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/103683933