链接:
https://www.nowcoder.com/acm/contest/115/G
来源:牛客网
来源:牛客网
题目描述
周末,小Q喜欢在PU口袋校园上参加各种活动刷绩点,体验丰富多彩的大学生活。
但是每个活动有各自的开始时间、结束时间、Happy值以及绩点数,活动之间可能存在时间冲突。
小Q是一个认真踏实的女孩,她在同一时间只会参加一个活动。
给出每一天的活动数,求小Q在同一天内所能获得的最大Happy值 与 绩点数。
小Q是一个活泼开朗的女孩,她总是寻求最大的Happy值,如果Happy值相同,才会尽可能使绩点数更多。
输入描述:
第一行输入一个整数T(表示样例个数) 接下来T组样例 每组样例第一行输入一个整数N(表示有几项活动) 接下来N行,每行输入s,e,h,p 4个整数,分别代表一个活动的开始时间、结束时间、Happy值以及绩点数 0<=s<e<=24,1<=h,p<=100,1<=T,N<=20
输出描述:
输出T行 一行输出一个样例对应的结果 小Q在一天内所能获得的最大 Happy值 与 绩点数
一维数组版:无注释(下面有二维数组注释版)
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#define N 25
int happy[N],point[N];
struct activity {
int s,e,h,p;
bool friend operator <(activity a,activity b) {
return a.s < b.s;
}
}ac[105];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>ac[i].s>>ac[i].e>>ac[i].h>>ac[i].p;
sort(ac,ac+n);
memset(happy,0,sizeof(happy));
memset(point,0,sizeof(point));
for(int i=0;i<n;i++) {
for(int j=ac[i].e;j<=24;j++) {
if(happy[j] < happy[ac[i].s] + ac[i].h) {
happy[j] = happy[ac[i].s] + ac[i].h;
point[j] = point[ac[i].s] + ac[i].p;
}else if(happy[j] == happy[ac[i].s] + ac[i].h) point[j] = max(point[j],point[ac[i].s]+ac[i].p);
}
}
cout<<happy[24]<<" "<<point[24]<<endl;
}
return 0;
}
/*题型:01背包*/
/*思路:使用二维数组来记录选择与否所能达到的最优状态*/
/*动态转移方程:m=hp[i-1][v[i].s]+v[i].h,n=hp[i-1][c]);hp[i][c]=max(m,n);*/
/* x=sc[i-1][v[i].s]+v[i].p,y=sc[i-1][c];*/
/* if(m>n) sc[i][c]=x;*/
/* if(m==n) sc[i][c]=max(x,y);*/
/* if(m<n) sc[i][c]=y;*/
/*解释-关于hp: 若是选择当前i活动,那么前(i-1)件活动的底线时间是v[i].s,获得的hp是在此底线时间下的hp最大值加上当前的hp值*/
/* happiness 若是不选择,那么前i-1件活动就拥有了现在的未经占用的底线时间,获得的hp是在此底线时间下的最大值*/
/*解释-关于sc: 若是选择第i活动(m>n),获得的sc是之前i-1件活动在底线时间为v[i].s条件下获得的sc值加第i个活动的sc值*/
/* score 这并不一定是sc的最佳值*/
/* 若是获得的hp相等(m==n),这时就要通过选或不选来使能获得的sc利益最大化了*/
/* 若是不选择第i活动(m<n),获得的sc是之前i-1件活动在当前底线时间条件下能获得的sc值*/
/*Ps:一定注意若是选择,之前i-1件活动拥有的底线时间是固定的(=v[i].s),而不是现有时间-当前活动时长 */
/*Ps.2: 关于绩点sc,hp相等时一定要判断哪种情况获得的sc更大;而不是在m!>n之后简单的赋值为sc[i][c]]*/
#include<bits/stdc++.h>
using namespace std;
struct info{
int s,e,h,p;
//start end happy point
bool friend operator <(info a,info b)
{
return a.e<b.e;
}
};
vector<info> v;
int hp[25][25];
int sc[25][25];
int main()
{
int T,N;
int i,j;
int m,n;
cin>>T;
while(T--)
{
v.clear();
memset(hp,0,sizeof(hp));
memset(sc,0,sizeof(sc));
cin>>N;
for(i=0;i<N;i++)
{
info x;
cin>>x.s>>x.e>>x.h>>x.p;
v.push_back(x);
}
sort(v.begin(),v.end());
for(i=24;i>=v[0].e;i--)
{
hp[0][i]=v[0].h;
sc[0][i]=v[0].p;
}
for(i=1;i<N;i++)
for(j=24;j>=0;j--)
{
n=hp[i-1][j];
if(j>=v[i].e)
{
m=hp[i-1][v[i].s]+v[i].h;
hp[i][j]=max(m,n);
if(m>n) sc[i][j]=sc[i-1][v[i].s]+v[i].p;
else if(m==n) sc[i][j]=max(sc[i-1][j],sc[i-1][v[i].s]+v[i].p);
else sc[i][j]=sc[i-1][j];
}
else
{
hp[i][j]=n;
sc[i][j]=sc[i-1][j];
}
}
cout<<hp[N-1][24]<<" "<<sc[N-1][24]<<endl;
}
return 0;
}
本文介绍了一种通过算法解决活动选择问题的方法,旨在帮助用户在有限的时间内选择能够带来最大快乐值和绩点数的活动组合。通过01背包问题的思路,利用动态规划实现了最优解的计算。

被折叠的 条评论
为什么被折叠?



