题目描述
从前有2只狗,大的叫大狗,小的叫小狗,它们2个合起来就是狗儿们,使用英语的人把它们写作Girlman,传来传去,到最后大家决定叫它们格尔曼。它们 的叫声很特别,但是它们十分吝啬它们的叫声,你为了听到它们的叫声,决定买狗饼干送给它们吃,不同种类的饼干能让它们叫的次数不一样,同一块饼干对于大小 格尔曼的效果也不一样。它们很贪婪,如果你只给其中一只格尔曼吃狗饼干或者给两只格尔曼吃的不一样,有一只就会不高兴,因此你买狗饼干的时候总要两块两块 地买,而且现在每类饼干也只有2块(想要多的也没得)。现在不是流行节约型社会吗?因此你也不能浪费,你要求的是在满足你要听格尔曼叫声次数要求的情况 (两只格尔曼实际叫的次数都不小于你的要求即可)下的最小花费是多少。
输入
输入文件的第一行为3个整数n、s、b,分别表示狗饼干的类数、你想听到的小格尔曼的叫声次数和大格尔曼的叫声次数,接下来有n行,第i+1行有3个整数si、bi、ci,分别表示第i类狗饼干能让小格尔曼叫的次数、能让大格尔曼叫的次数和该类饼干的单价。
30%的数据满足1<=n<=30;
100%的数据满足1<=n<=1000、1<=s,b<=50、0<=si ,bi ,ci <=2147483647。
输出
输出文件只有一个整数,为满足你的要求情况下的最小花费。
样例输入
5 5 10
1 2 5
2 4 10
3 7 8
1 11 36
6 0 18
样例输出
36
题目链接点击打开链接
简单的01背包但容易被惯性思维影响。
题目的关键再以对于当前的状态的前一个状态是否存在,很简单如果前一个状态都不存在,当前状态也不需要考虑了。
所以2维的dp我们应该倒着推测,及循环到的其实是当前状态的前一个状态(及dp[i][j])。
#include <bits/stdc++.h>
using namespace std;
long long int dp[55][55];
int main(){
long long int n,s,b;
scanf("%lld %lld %lld",&n,&s,&b);//分别表示狗饼干的类数、你想听到的小格尔曼的叫声次数和大格尔曼的叫声次数
long long int a,d,c;
memset(dp,-1,sizeof(dp));//用-1表示目前状态没有达到
dp[0][0]=0;
for(int i=1;i<=n;i++){
scanf("%lld %lld %lld",&a,&d,&c);//分别表示第i类狗饼干能让小格尔曼叫的次数、能让大格尔曼叫的次数和该类饼干的单价
for(int j=s;j>=0;j--)
for(int k=b;k>=0;k--){
if(dp[j][k]==-1)//如果当前的状态不存在,那么不可能推出下一个状态
continue;
long long int x=min(s,j+a);
long long int y=min(b,k+d);
if(dp[x][y]==-1)
dp[x][y]=dp[j][k]+c;
else
dp[x][y]=min(dp[x][y],dp[j][k]+c);
}
}
printf("%lld\n",dp[s][b]*2);
return 0;
}