2.16 T2题解

题2 饥荒

【问题描述】

Lzh实在是太饿了。他打算在接下来的n天中自己做菜。每天做一道菜。他能做各种各样的不同的菜。他事先就知道做各道菜的花费以及各道菜对他的好处值。但如果Lzh连续两天做同一道菜,那么第二天得到的该到菜的好处值将是第一天的得到的该道菜的好处值的一半。如果一道菜连续做i(i >= 3)天,那么从第三天开始一直到第i天,Lzh每天从该道菜上得到的好处值将为0。
打个比方来说,Lzh连续3天做同一道好处值为v的菜,那么这三天他得到的好处总值将为1.5*v。
帮助Lzh确定这n天中,每天他该做什么菜,使得做菜的总花费在不超过Lzh现有的钱数的情况下,好处总值最大。

【输入文件】

第一行3个数, n n (1 <= n n <= 21) , m m (1 <= m m <= 50), k k (0 <= k k <= 100)。 n n 表示 L z h Lzh 做菜的总天数。 m m 表示 L z h Lzh 会做的菜的总数。 k k 表示 L z h Lzh 现有的钱数。
接下来的m行,描述了每道菜的情况。
每行两个数$c(1 <= c <= 50),a(1 <= a <= 10000)。c表示该道菜的花费,a表示该道菜的好处值。**

【输出文件】

仅一行,输出一个数,表示这n天中Lzh能够得到的最大的好处总值。答案保留一位小数。如果不能保证每天都让Lzh吃到菜,则输出0.0。
【输入样例一】
2 1 5
3 5
【输出样例一】
0.0
【样例解释】
Lzh共要做2天菜,他只会做1道菜。该道菜的花费为3,好处值为5。
那他这两2天只能做这道菜,总共的花费为3 + 3 = 6。但他一共只有5块钱。6>5。不能保证他每天都吃到菜,所以输出0.0。

【输入样例二】
3 5 20
2 5
18 6
1 1
3 3
2 3
【输出样例二】
13.0
【样例解释】
一种可行的方案为第1天做第1种菜,第2天做第5种菜,第3天做第1种菜。总花费2 + 2 + 2 = 6 < 20,好处总值为5 + 3 + 5 = 13。

【输入样例三】
5 1 20
1 5
【输出样例三】
7.5
【样例解释】
连续5天,每天都吃同一道菜。总花费1 + 1 + 1 + 1 + 1 = 5 < 20,由于连续5天吃同一道菜,所以Lzh只有第1天和第2天得到了好处值,后3天得到的好处值为0,所以好处总值为5 + 5 / 2 = 7.5。

Mentality

我的大方向是DP
请看注释

const int N=21+10;
const int M=50+5;
const int K=100+20;

double f[N][M][N][K];
//第n天
//选了第m道菜
//这道菜吃了几天(包括这一天)
//用了k元
//f[][][][]=最大好处值

分别枚举 f f 的每一位
然后对于两顿饭一样的
特殊处理即可

for(i=1;i<=n;i++) { //days
	for(j=1;j<=m;j++) { //now meals
		for(v=c[j];v<=k;v++) { //money
			for(e=1;e<=m;e++) { //last meals
				if(e==j) continue; //special
				for(u=1;u<=i;u++) {//times(now!=last)
					if(f[i-1][e][u][v-c[j]]<1&&i!=1) //都饿死了就不转移
						continue;
					f[i][j][1][v]=max(f[i][j][1][v],f[i-1][e][u][v-c[j]]+a[j]);
					//now!=last,就只吃了一天
				}
			}
			//now==last部分
			//第一次和第二次特殊处理
			if(i==1) 
				f[i][j][1][v]=max(f[i][j][1][v],f[i-1][j][0][v-c[j]]+a[j]);
			if(i>=2&&f[i-1][j][1][v-c[j]]>1) 
				f[i][j][2][v]=max(f[i][j][2][v],f[i-1][j][1][v-c[j]]+a[j]*0.5);
			//3-i次就一样了
			for(u=3;u<=i;u++) {
				if(f[i-1][j][u-1][v-c[j]]<1) continue;
				f[i][j][u][v]=max(f[i][j][u][v],f[i-1][j][u-1][v-c[j]]);//from u-1
			}
		}
	}
}
完整代码

mycode:

#include<bits/stdc++.h>
using namespace std;
const int N=21+10;
const int M=50+5;
const int K=100+20;
int n,m;
int k;
int c[M]; //c表示该道菜的花费,
double a[M];  //a表示该道菜的好处值。
double f[N][M][N][K];
#define Max(a,b) ((a>b) ? a : b)
int main()
{
	freopen("hungry.in","r",stdin);
	freopen("hungry.out","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	int i,j,u,v,e;
	for(i=1;i<=m;i++) 
		cin>>c[i]>>a[i];
	for(i=1;i<=n;i++) { //days
		for(j=1;j<=m;j++) { //now meals
			for(v=c[j];v<=k;v++) { //money
				for(e=1;e<=m;e++) { //last meals
					if(e==j) continue;
					for(u=1;u<=i;u++) {
						if(f[i-1][e][u][v-c[j]]<1&&i!=1) continue;
						f[i][j][1][v]=max(f[i][j][1][v],f[i-1][e][u][v-c[j]]+a[j]);
					}
				}
				//now==last
				if(i==1) 
					f[i][j][1][v]=max(f[i][j][1][v],f[i-1][j][0][v-c[j]]+a[j]);
				if(i>=2&&f[i-1][j][1][v-c[j]]>1) 
					f[i][j][2][v]=max(f[i][j][2][v],f[i-1][j][1][v-c[j]]+a[j]*0.5);
				for(u=3;u<=i;u++) {
					if(f[i-1][j][u-1][v-c[j]]<1) continue;
					f[i][j][u][v]=max(f[i][j][u][v],f[i-1][j][u-1][v-c[j]]);
				}
			}
		}
	}
	double ans=0;
//	for(i=1;i<=n;i++)
//		for(j=1;j<=m;j++) 
//			for(u=1;u<=n;u++) 
//				for(v=0;v<=k;v++) 
//					cout<<"f("<<i<<","<<j<<","<<u<<","<<v<<")"<<" = "<<f[i][j][u][v]<<endl;
	for(j=1;j<=m;j++) 
		for(u=1;u<=n;u++) 
			for(v=0;v<=k;v++) 
				ans=Max(ans,f[n][j][u][v]);//,
	if(ans<1) cout<<"0.0"<<endl;
	else cout<<fixed<<setprecision(1)<<ans<<endl;
	return 0;
}
发布了17 篇原创文章 · 获赞 3 · 访问量 1705

猜你喜欢

转载自blog.csdn.net/qq_45646484/article/details/104345586
T2