洛谷p1717
https://www.luogu.com.cn/problem/P1717
题意:
思路1(动态规划):
考虑状态表示:dp[i][j],表示前i个中调了j小时的最大值,有两种转移方式,要么不调,要么调k分钟,所以转移方程是:dp[i][j]=max(dp[i][j],dp[i-1][j-t[i]-k]+k*f-sum(d))
题解:
const int N = 30, M = 1010;
int f[N], t[N], d[N];
int dp[N][M];
void solve() {
int n, h;
scanf("%lld%lld", &n, &h);
h *= 60;
for (int i = 1;i <= n;i++) scanf("%lld", &f[i]);
for (int i = 1;i <= n;i++) { scanf("%lld", &d[i]); }
for (int i = 1;i < n;i++) { scanf("%lld", &t[i]); t[i] *= 5; }
int cost = 0;
for (int i = 1;i <= n;i++) {
for (int j = cost+5;j <= h;j += 5) {//假设当前层要钓鱼,那么最小的起始时间
int sum = 0;//是cost+5,dp[i][cost]一定是0,
for (int k = 1;k * 5 <= j;k++) {//枚举当前层钓鱼时间
if (j - t[i - 1] - k * 5 >= 0) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - t[i - 1] - k * 5] + k * f[i] - sum);
sum += d[i] * k;
}
}
}
cost += t[i];
}
int ret = 0;//因为不一定在最后一个点结束,所以取所有状态的最值,
for (int i = 1;i <= n;i++) {
for (int j = 0;j <= h;j += 5) {
ret = max(ret, dp[i][j]);
}
}
printf("%lld\n", ret);
}
思路二(贪心):
因为每次走的所花费的时间是不可避免的,所以可以先减去走路所花费的时间,然后剩下的时间全部用来钓鱼,每次取出最大值,(相当于已经知道在某个点需要调多少分钟,而不是返回上一个点继续钓鱼)
题解:
struct T {
int f, id;
bool operator < (const T& t)const {
// return bool
return f < t.f;
}
}a[30];
int d[30], t[30];
void solve() {
int n, h;
scanf("%lld%lld", &n, &h);
h *= 60;
for (int i = 1;i <= n;i++) {
auto& [x, y] = a[i];
scanf("%lld", &x);
y = i;
}
priority_queue<T> heap;
for (int i = 1;i <= n;i++) { scanf("%lld", &d[i]); }
for (int i = 1;i < n;i++) { scanf("%lld", &t[i]);t[i] *= 5; }
int ret=0;
auto clear=[&](){
while(heap.size()) heap.pop();
};
for(int i=1;i<=n;i++){//枚举钓鱼终点;
h-=t[i-1];
clear();
int cur=0;
for(int j=1;j<=i;j++) heap.push(a[j]);//将终点前的每一个钓鱼点放入堆中取最大
for(int j=5;j<=h;j+=5){
auto [x,y] = heap.top();
heap.pop();
if(x>0) cur+=x;
heap.push({x-d[y],y});
}
ret=max(ret,cur);
}
printf("%lld\n",ret);
}
本文作者:指引盗寇入太行
本文链接:https://www.cnblogs.com/koto-k/p/15491767.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步