题目地址
AC代码
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
long long int mini = pow(2,60);
void calculate(long long int *list,long long int *levelDiff,long long int quantity,long long int now,long long int pass,long long int maxi,long long int low,long long int diff,long long int sum,int *mark){
if(levelDiff[now]>maxi)maxi = levelDiff[now];
if(levelDiff[now]<low)low = levelDiff[now];
if(maxi-low>diff)return;
mark[now]=1;
for (int i = 1; i <= quantity; ++i) {
if(now==i)continue;
if(mark[i]==1)continue;
if(list[now*(quantity+1)+i]!=-1){
if(now!=1)calculate(list,levelDiff,quantity,i,now,maxi,low,diff,sum+list[pass*(quantity+1)+now],mark);
else calculate(list,levelDiff,quantity,i,now,maxi,low,diff,0,mark);
mark[i]=0;
}
}
if(now!=1)sum+=list[now*(quantity+1)+now]+list[pass*(quantity+1)+now];
else sum+=list[now*(quantity+1)+now];
sum<mini?mini=sum:mini=mini;
}
int main() {
long long int diff,quantity;
cin>>diff>>quantity;
long long int list[quantity+1][quantity+1];
long long int levelDiff[quantity+1];
int mark[quantity+1];
memset(mark,0,sizeof(mark));
memset(list,-1, sizeof(list));
for (long long int i = 1; i <= quantity; ++i) {
long long int weight,level,things;
cin>>weight>>level>>things;
list[i][i]=weight;
levelDiff[i]=level;
for (long long int j = 0; j < things; ++j) {
long long int temp;
cin>>temp;
cin>>list[i][temp];
}
}
calculate(*list,levelDiff,quantity,1,1,levelDiff[1],levelDiff[1],diff,0,mark);
cout<<mini;
return 0;
}
题解和题目思路
请不要吐槽我那个又臭又长的参数列表//为什么要用long long,问题目为什么不说清楚数据范围先好了。
这道题看别人的题解是用迪杰斯特拉算法查找最短路径做的,我自己是没写出来就是了,按照我的思路来写过于复杂。
于是我改用了DFS来解这道题
可以把物品之间的优惠兑换关系看作是图,物品为顶点,两个物品之间的优惠价格为有向带权的边,如果是自己换自己(直接购买)则为自环边,权值为原价。
建立好图之后即可用DFS对其进行搜索。从序号1的物品开始,分为继续换和不继续换两个状态。如果还有的换,则更新sum,丢入DFS的下一阶段,如果没有的换或者所有可以换的情况已经实现了,则匹配原价购买当前物品得到的总价值,与最小值比较,完成DFS后输出最小值即可。