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

题意:
大概意思就是说一个人有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;
}

浙公网安备 33010602011771号