冒险岛
Description
这时,我们的主人公F1(没什么名字好取,为了简单,暂且这样)来到了一块神秘的地方——冒险岛,这是一个充满荆棘的地方,随时都可能有生命危险。
F1也深知这一点,他做好了充分的准备,他已经通过高空扫描技术对冒险岛进行了分析:
冒险岛是由
N∗M
个单位方格组成,即
N
行
格子有两种形式:沙漠与圣水湖。
每一个沙漠都有一个摧毁值
D
,当F1走到一个摧毁值为
主人公F1可以向下(行数增加)向右(列数增加)的移动,它必须从
(1,1)
走到
(n,m)
(第
n
行
由于某种不为人知的力的作用(外星人?宇宙引力?或是四维空间中的“物质”?谁知道!),使得从
(1,1)
到
(n,m)
一定会经过沙漠。你不必担心F1的生命,也许他的生命值有无穷大,也许他凭着坚强的意志可以在生命值为负数的情况下移动——他一定能走出这个岛,在最后走出
(n,m)
时,他需要用他得到的所有圣水去弥补他失去的生命值,你只需关心他的“精神面貌值”:得到的圣水与失去的生命值的比值。
你需要使“精神面貌值”最大。
Input
第一行有两个整数
N
,
如果小于
0
,则表示摧毁值为
Output
仅一个数,表示最大“精神面貌值”,精确到小数点后 4 位。
Sample Input
3 3
100 -20 -30
-100 -100 -100
-100 100 –100
Sample Output
0.9091
Solution
二分答案
即
然后就是动归就最大路径了,若最大值小于 0 <script type="math/tex" id="MathJax-Element-1525">0</script> ,则不成立。
Solution
#include <iostream>
#include <cstdio>
#define LL long long
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
LL n,m;
double Maxn;
LL map[400][400];
double f[400][400];
bool judge(double x){
for(LL i=1;i<=n;i++)
for(LL j=1;j<=m;j++){
f[i][j]=Max(f[i-1][j],f[i][j-1]);
if(map[i][j]<0)f[i][j]+=x*map[i][j];
else f[i][j]+=map[i][j];
}
return f[n][m]>=0;
}
double binary(double l,double r){
double ans=-1;
while(r-l>=1e-5){
double mid=(l+r)/2;
if(judge(mid)){
ans=Max(ans,mid);
l=mid;
}
else{
r=mid;
}
}
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
for(LL i=1;i<=n;i++)
for(LL j=1;j<=m;j++){
scanf("%lld",&map[i][j]);
if(map[i][j]>0)Maxn+=map[i][j];
}
printf("%.4lf\n",binary(0,Maxn));
return 0;
}