记 2024.4.15
P2079
烛光晚餐
题目背景
小明准备请小红去一家咖啡厅,共进烛光晚餐。小红高兴地和他一起去了咖啡厅。
题目描述
小红说:“小明,你点菜吧。”小明看到菜单上有N道菜,每道菜的价格是Ci。小明对每道菜的喜爱程度是Xi,小红对每道菜的喜爱程度是Yi。(喜爱程度可能为负数)(小明:以我对她的了解,我给你的数据不会错的)
小明带了V元钱,他点的菜的总价格不能超过V(小明:当然得我请客啦,显得我大方。)
小明希望让小红吃得开心,所以当然要让她的总喜爱程度尽量大。当然,小明也要考虑自己的感受,点的所有菜的总喜爱程度需要大于等于0。(小明:要是我吃得不好,她看见我会难过的)
请你帮小明写一个程序,计算出他的总喜爱程度大于等于0的前提下,小红的喜爱程度的最大值。(小明:你的程序一定要靠谱啊,我得给她一个好印象)
输入格式
第1行,两个正整数N,V。
之后N行,每行3个空格隔开的正整数Ci,整数Xi,Yi。
输出格式
一行,一个正整数,表示他的总喜爱程度大于等于0的前提下,小红的喜爱程度的最大值。如果这个最大值小于0,输出-1.
样例 #1
样例输入 #1
4 10
5 -1 3
2 2 2
11 -5 100
3 -3 10
样例输出 #1
5
提示
对于10%数据,N<=10,V<=50。
对于30%数据,Xi,Yi>=0.
对于全部数据,N<=100,V<=500,|Xi|<=5,|Yi|<=1000.
记得这种有容量的选物品问题要先考虑背包,不要在想半天贪心了,我真是弱智了,居然没去想背包。
负数dp记得加偏移量,记得初始化 数组为最坏的。
状态转移方程
dp[i][j+500]=max(dp[i][j+500],dp[i-w[i]][j+500-w1[i]])
为背包容量, 为喜欢值容量。
code
#include <iostream>
#include <cstring>
using namespace std;
const int N=110,M=1010;
int f[M][M];
int n,m,m1;
int v[N],w[N],w1[N],minn[M];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>w[i]>>w1[i]>>v[i];
int ans=-0x3f3f3f3f;
memset(f,-0x3f,sizeof f);
f[0][500]=0;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=w[i];j--)
{
for(int k=500;k>=-500+w1[i];k--)
{
if(k-w1[i]<=500&&k-w1[i]>=-500)
f[j][k+500]=max(f[j][k+500],f[j-w[i]][k+500-w1[i]]+v[i]);
}
}
}
for(int j=m;j>=0;j--)
{
for(int k=500;k>=0;k--)
{
ans=max(ans,f[j][k+500]);
}
}
cout<<ans;
return 0;
}
P2865
[USACO06NOV] Roadblocks G
题面翻译
贝茜把家搬到了一个小农场,但她常常回到 FJ 的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。
贝茜所在的乡村有 条双向道路,每条路都联结了所有的 个农场中的某两个。贝茜居住在农场 ,她的朋友们居住在农场 (即贝茜每次旅行的目的地)。
贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
输入格式
Line 1: Two space-separated integers: N and R
Lines 2..R+1: Each line contains three space-separated integers: A, B, and D that describe a road that connects intersections A and B and has length D (1 ≤ D ≤ 5000)
输出格式
Line 1: The length of the second shortest path between node 1 and node N
样例 #1
样例输入 #1
4 4
1 2 100
2 4 200
2 3 250
3 4 100
样例输出 #1
450
提示
Two routes: 1 -> 2 -> 4 (length 100+200=300) and 1 -> 2 -> 3 -> 4 (length 100+250+100=450)
直接在dijkstra时求严格次短路,松弛时就可以更新次短路变成松弛之前的了,注意不需要 数组,因为不能保证目前的最短路是最短时,目前的次短路是最短的。
注意特判 不是目前求得的最短路 ,如果不判,就会浪费又遍历一遍所有边,那时间复杂度就假了。
好好想,你其实可以想出来,不要太早判假,注意无用情况是可以去除的,所以可以去除他们大量优化时间复杂度。
code
口胡。
考虑 题解,优化也在里面。

浙公网安备 33010602011771号