題目描述
輸入格式
第一行兩個正整數 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;
}