Gym 100820 J Olympics —— 思维

This way

题意:

你现在有一个能量E,你现在要举重,你能举起的最大重量为S,但是你不知道S是多少,只知道它最少为25,最多为225。你现在可以尝试举重,如果你尝试的重量大于等于S,那么你的能量-E1,当前重量记录答案。如果小于S,你的能量-E2,不记录答案。你能继续尝试举重当且仅当你的能量>0,问你你能够举的重量和S的最小差距是多少

题解:

这道题我是没想出来,而且其实题解我也没太看懂,也不知道我理解的是不是对的。
大致就是,dp[i]表示能量为i的时候,能将这个区间实际分成多少份,这时候就有一个问题,其实我不知道当前划分在哪里,也不知道S有多大,我们当前就是凭空划一刀:
在这里插入图片描述
然后会发现它成功与不成功在之后的话,区间是不会有交集的,然后可以知道,最优一定是将所有区间平分,那么其实不是直接能划几道就是分成几个,而是成功与失败的所有可能性平分(这里需要理解一下)所以 d p [ i ] = 1 + d p [ i E f a l s e ] + d p [ i E s u c c ] dp[i]=1+dp[i-E_{false}]+dp[i-E_{succ}] ,差不多是这个意思:
在这里插入图片描述
但是由于25的存在,所以最后分成了两种情况:由于我们是划dp[E]刀,所以是分成了dp[E]+1个区间,然后第一种是直接做:225/(dp[E]+1),第二种是现在25这里划一刀:
200/dp[E],取最小的即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+5;
int dp[N];
int main()
{
    int n,a,b;
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++){
        dp[i]=1;
        if(i>=a)
            dp[i]+=dp[i-a];
        if(i>=b)
            dp[i]+=dp[i-b];
        if(dp[i]>5e8)
            dp[i]=5e8;
    }
    printf("%.6f\n",min(200.0/dp[n],225.0/(dp[n]+1)));
    return 0;
}

发布了584 篇原创文章 · 获赞 33 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/105127142