P1802 5倍经验日
背包还是理解不到位呀QWQ
思路
简单的01背包,不过实在01背包的基础上加了一个小小的变化,也就是不用药打也是要算在重量内。
所以可得动态转移方程:
f[j]=max(f[j]+lost[i],f[j-use[i]]+win[i]) (当j>=use[i]时)
f[j]=f[j]+lost[i] (当j<use[i]时)//重点
注意:
由于有时取不到赢的价值,但一定能取到输的价值,所以循环一定要循环到0,然后判断能否取赢的。举个简单的例子,如果他用药数比x还大,那么循环到wi就肯定跳过了,而输的价值就被吃了
错误题解
#include<bits/stdc++.h>
using namespace std;
long long f[1010];
int main()
{
int n, x;
long long lose[1010], win[1010], use[1010];
cin>>n>>x;
for(int i = 1; i <= n; i++)
cin>>lose[i]>>win[i]>>use[i];
for(int i = 1; i <= n; i++)
for(int j = x; j >= use[i]; j--)
{
f[j] = max (f[j] + lose[i], f[j - use[i]] + win[i]);
}
cout<<f[x] * 5<<endl;
}
正确题解
#include<bits/stdc++.h>
using namespace std;
long long f[1010];
int main()
{
int n, x;
long long lose[1010], win[1010], use[1010];
cin>>n>>x;
for(int i = 1; i <= n; i++)
cin>>lose[i]>>win[i]>>use[i];
for(int i = 1; i <= n; i++)
{
for(int j = x; j >= use[i]; j--)
{
f[j] = max (f[j] + lose[i], f[j - use[i]] + win[i]);
}
for(int j = use[i] - 1; j >= 0; j--) // 保证至少取到输的价值
f[j] += lose[i];
}
cout<<f[x] * 5<<endl;
}
P2347 砝码称重
题解
没什么好说的,背包套路
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[10] = {1, 2, 3, 5, 10, 20};
int x, index = 0;
int cnt[1005], f[1005];
memset(f, 0,sizeof(f));
for(int i = 0; i < 6; i++)
{
cin>>x;
while(x--) cnt[++index] = a[i];
}
f[0] = 1;
for(int i = 1; i <= index; i++)
for(int j = 1000; j >= 0; j--)
{
if(f[j] == 1) f[j + cnt[i]] = 1;
}
for(int i = 2; i<= 1000; i++)
f[i] +=f[i - 1];
cout<<"Total="<<f[1000]<<endl;
}