题目描述
输入格式
第一行两个正整数 n,hp ,含义如题目所述。
第二行 n 个整数,分别是 a[1]..a[n]。
输出格式
输出一个数,即最大的 cd ,cd 是一个正整数。
如果 cd 没有上限,输出 "No upper bound.";如果无论如何都不能存活,输出 -1。
样例数据 1
备注
【数据范围】
对于 30% 的数据,n≤12
对于 100% 的数据,n≤500, |a[i]| ≤1000
分析:
二分答案,用贪心+记忆化搜索建图做
贪心:受了伤一定马上用魔棒
记忆化搜索:二分答案只是判断能否成立,该点搜索过了就别再搜了
建图:预处理积累魔棒及使用的情况,当必须使用魔棒时就连边
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
int n,hp;
int f[510000];
int a[510000];
bool dp[510000];
struct node
{
int next;
int to;
};
node bian[1000010];
int first[510000];
int size;
void inser(int a,int b)
{
bian[++size].to=b;
bian[size].next=first[a];
first[a]=size;
}
long long read()
{
long long k=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+c-'0'; c=getchar();}
return k*f;
}
void dfs(int x,int cd)
{
int i,u;
dp[x]=1;
for(i=first[x];i;i=bian[i].next)
{
u=bian[i].to;
if(dp[n]) return;
if(u-x>=cd||x==0||u==n)
{
if(!dp[u])
dfs(u,cd);
}
}
}
bool check(int x)
{
memset(dp,false,sizeof(dp));
dfs(0,x);
if(dp[n]) return true;
return false;
}
int main()
{
// freopen("magic.in","r",stdin);
// freopen("magic.out","w",stdout);
int i,j,k;
n=read();
hp=read();
f[0]=hp;
for(i=1;i<=n;i++)
{
a[i]=read();
f[i]=f[i-1]-a[i]+15;
}
for(i=0;i<n;i++)
{
int dd=f[i];
for(j=i+1;j<=n;j++)
{
dd=dd-a[j];
if(dd<=0) break;
inser(i,j);
}
}
int head=0;
int tail=n+1;
int mid;
while(tail-head>1)
{
mid=(head+tail)>>1;
if(check(mid))
{
head=mid;
}
else
tail=mid;
}
if(head==0)
{
cout<<"-1";
return 0;
}
if(head==n)
{
cout<<"No upper bound.";
return 0;
}
cout<<head;
return 0;
}