泡泡

2021第十二届山东省赛 H(01背包) G(模拟)

H(01背包)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210510222446671.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUwMjg1MTQy,size_16,color_FFFFFF,t_70)

题意:
大概意思就是说一个人有H的生命值,S的体力值,他需要打怪获得奖励金币,打一个怪会损失掉$h_i$的生命值和$s_i$的体力值,当生命值小于等于0时,他就会死掉,但是如果体力值小于零,他的生命值就会减掉相应体力负值的绝对值,问在不死的情况下,获得最大的金币值。

思路:
经典的01背包问题,其实就是容量变成二维的了,其它的不变,需要从后往前遍历容量,因为是二维滚动数组。

状态表示:
$dp[i][j]$为$i$的生命值和$j$的体力值能够获得的最大金币数

转移方程:
体力值不为负时:
dp[j][k] = max(dp[j][k],dp[j-h[i]][k-s[i]]+w[i])
体力为负时:
生命值最终为(j-h[i])+(k-s[i])
dp[j][k] = max(dp[j][k],dp[j+k-s[i]-h[i]][0]+w[i])


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3+5;
ll dp[305][305];
ll s[N],h[N],w[N];

int main()
{
    int n,S,H;
    cin>>n>>S>>H;
    for(int i=1;i<=n;i++) cin>>s[i]>>h[i]>>w[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=300;j>=0;j--)
        {
            for(int k=300;k>=0;k--)
            {
                if(j-s[i]>0 && k>=h[i])
                    dp[j][k] = max(dp[j][k],dp[j-s[i]][k-h[i]]+w[i]);
                else if(j>s[i] && j+k-h[i]-s[i]>0)
                    dp[j][k] = max(dp[j][k],dp[j+k-h[i]-s[i]][0]+w[i]);
            }
        }
    }
    
    cout<<dp[S][H]<<'\n';
    return 0;
}

G

题意:
具体就是对一个假分数算出后k为小数,进行输出。

思路:
先输出整数位,再输出小数位
每个小数位就是乘10,模n的操作

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;

int main()
{
    ll sum = 0;
    cin>>n>>k;
    for(int i=1;i<=n;i++) 
    {
        int num;cin>>num;
        sum+=num;
    }
    cout<<sum/n<<".";
    int t = sum%n;
    for(int i=1;i<=k;i++)
    {
        t*=10;
        cout<<t/n;
        t%=n;
    }
    return 0;
}
posted @ 2021-05-10 23:26  行码棋  阅读(85)  评论(0)    收藏  举报