昂贵的聘礼 (dfs)

2023-12-28 07:58
文章标签 dfs 聘礼 昂贵

本文主要是介绍昂贵的聘礼 (dfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

昂贵的聘礼

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)
Total Submission(s) : 68   Accepted Submission(s) : 21
Problem Description
年轻的探险家来到了一个印第安部落里。在那里他和酋长的女儿相爱了,于是便向酋长去求亲。酋长要他用10000个金币作为聘礼才答应把女儿嫁给他。探险家拿不出这么多金币,便请求酋长降低要求。酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币。如果你能够弄来他的水晶球,那么只要5000金币就行了。"探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格。探险家于是又跑到其他地方,其他人也提出了类似的要求,或者直接用金币换,或者找到其他东西就可以降低价格。不过探险家没必要用多样东西去换一样东西,因为不会得到更低的价格。探险家现在很需要你的帮忙,让他用最少的金币娶到自己的心上人。另外他要告诉你的是,在这个部落里,等级观念十分森严。地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。他是一个外来人,所以可以不受这些限制。但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。因此你需要在考虑所有的情况以后给他提供一个最好的方案。
为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi。如果两人地位等级差距超过了M,就不能"间接交易"。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。

Input
输入第一行是两个整数M,N(1 <= N <= 100),依次表示地位等级差距限制和物品的总数。接下来按照编号从小到大依次给出了N个物品的描述。每个物品的描述开头是三个非负整数P、L、X(X < N),依次表示该物品的价格、主人的地位等级和替代品总数。接下来X行每行包括两个整数T和V,分别表示替代品的编号和"优惠价格"。

Output
输出最少需要的金币数。

Sample Input
  
1 4 10000 3 2 2 8000 3 5000 1000 2 1 4 200 3000 2 1 4 200 50 2 0

Sample Output
  
5250

Source
PKU

中文题,不解释。

思路:

用的dfs,看很多人都是用的图论的知识做的,有点懵。。。图论掌握的还是不扎实。。。下面附上dfs的代码吧:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <string>
using namespace std;
int mp[105][105],price[105],level[105],dis[105],vis[105];//mp代表的有关系的并且之间的价格,level代表等级,price代表优惠的价格,dis代表每一时刻价格,vis表示是否买过
int v,maxl,minl,p;
int M,N,P,L,X,minn;
void dfs(int pos){int i;int t_max,t_min;for(i=2;i<=N;i++){if(mp[pos][i]!=-1&&vis[i]==0){    //有关系并且未购买过if(dis[pos]+mp[pos][i]<=minn){  //条件if(level[i]<=maxl&&level[i]>=minl){t_max=maxl; //临时变量t_min=minl;maxl = level[i] + M> maxl? maxl : level[i] + M;minl = level[i] - M > minl ? level[i] - M : minl;dis[i] = dis[pos] + mp[pos][i];vis[i] = 1;dfs(i);vis[i] = 0;maxl = t_max;minl = t_min;}}}}if(minn > dis[pos] + price[pos]) //找最小值minn = dis[pos] + price[pos];
}
int main()
{ios::sync_with_stdio(false);//int M,N,P,L,X;int p,v;int i,j;cin>>M>>N;memset(mp,-1,sizeof(mp));memset(dis, 0,sizeof(dis));memset(vis,0,sizeof(vis));for(i=1;i<=N;i++){cin>>P>>L>>X;level[i]=L;price[i]=P;for(j=1;j<=X;j++){cin>>p>>v;mp[i][p]=v;}}maxl=level[1]+M;minl=level[1]-M;vis[1]=1;minn=price[1];dfs(1);cout<<minn<<endl;return 0;
}
其他大牛的 dijkstra算法:  转自: 点击打开链接

枚举等级限制。以下转载

对于从u点出发到w点的路径中,他会跟很多等级的人交易,然而必须满足在路径中的点等级差不很超过一个M值,那么怎么对这样的问题求解呢?我没看报告前是很疑惑的!

假设如果给这条路径加上一个附加条件的话,情况可能就有所变化了,要求最短路中的所有点的等级在一个区间内[a,b],如果能够很好的给出这个区间的话,只要对图中的点进行上筛选即可了。

这个区间的确定显然不是随便的,那么就要根据一定的条件了,从题意中我们知道,最后所有的最短路都会汇集在1号点,也就是说1号点是所有最短路都存在的点,好了,这个条件很重要,这样我们就可以依照1号点来给定区间了,比如1号点等级为lev,那么也就是说在所有最短路的这些点都必须满足在[lev-M,lev+M]这个区间里面。好了,可能你会迫不及待将这个区间作为最后的区间,在想想,如果在这个区间内出现的两个点的他们之间的等级差超过了M值(这是存在的),显然,不符合题意了,所以这个区间还有继续缩小。其实只要稍微动动脑子,就可以找出这样的区间[lev-M,lev],[lev-M+1,lev+1],... ...,[lev,lev+M],首先这些区间都满足大区间的条件,而且如果将这些区间的某个作为筛选条件的话,在这个区间内的任意两个点的等级都不会超过M值,这就是很特别的地方了


#include <iostream>  
using namespace std;  #define INF 200000000  int map[110][110], n;  
int rank[110], value[110], dist[110];  
int mark[110], within[110];  int Dijkstra ()  
{  int i, j, k, min;  memset(mark,0,sizeof(mark));  for ( i = 1; i <= n; i++ )  dist[i] = map[1][i];  dist[1] = 0;  mark[1] = 1;  for ( i = 1; i <= n; i++ )  {  min = INF;  for ( j = 1; j <= n; j++ )  {  if ( !mark[j] && within[j] && dist[j] < min )  {  k = j;  min = dist[j];  }  }  if( min == INF )  break;  mark[k] = 1;  dist[k] = min;  for ( j = 1; j <= n; j++ )  if ( !mark[j] && within[j] && dist[k] + map[k][j] < dist[j] )  dist[j] = dist[k] + map[k][j];  }  min = INF;  for ( i = 1; i <= n; i++ )  if ( dist[i] + value[i] < min && mark[i] )  min = dist[i] + value[i];  return min;  
}  int main()  
{  int ranklimit, t, i, j, k;  cin >> ranklimit >> n;  for ( i = 1; i <= n; i++ )  for ( j = 1; j <= n; j++ )  map[i][j] = ( i == j ? 0 : INF);  for ( i = 1; i <= n; i++ )  {  cin >> value[i] >> rank[i] >> t;  for ( j = 0; j < t; j++ )  {  cin >> k;  cin >> map[i][k];  }  }  int chief = rank[1], min_cost = INF, cost;  for ( i = 0; i <= ranklimit; i++ )  {  memset(within,0,sizeof(within));  for ( j = 1; j <= n; j++ )  {  if ( chief - rank[j] <= ranklimit - i && rank[j] - chief <= i)  within[j] = 1;  }  cost = Dijkstra ();  if ( cost < min_cost )  min_cost = cost;  }  cout << min_cost << endl;  return 0;  }


这篇关于昂贵的聘礼 (dfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/545378

相关文章

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

ural 1149. Sinus Dances dfs

1149. Sinus Dances Time limit: 1.0 second Memory limit: 64 MB Let  An = sin(1–sin(2+sin(3–sin(4+…sin( n))…) Let  Sn = (…( A 1+ n) A 2+ n–1) A 3+…+2) An+1 For given  N print  SN Input One

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

nyoj99(并查集+欧拉路+dfs)

单词拼接 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 5 描述 给你一些单词,请你判断能否把它们首尾串起来串成一串。 前一个单词的结尾应该与下一个单词的道字母相同。 如 aloha dog arachnid gopher tiger rat   可以拼接成:aloha.arachnid.dog.gopher.rat.tiger 输入 第一行是一个整

【CF】E. Anya and Cubes(双向DFS)

根据题意的话每次递归分3种情况 一共最多25个数,时间复杂度为3^25,太大了 我们可以分2次求解第一次求一半的结果,也就是25/2 = 12,记录结果 之后利用剩余的一半求结果 s-结果 = 之前记录过的结果 就可以 时间复杂度降低为 3 ^ (n/2+1) 题目链接:http://codeforces.com/contest/525/problem/E #include<set

力扣 797. 所有可能路径【DFS】

1. 题目 2. 代码 DFS , 直接见代码 class Solution {public:vector<int> path;vector<vector<int>> res; // 结果集void dfs(vector<vector<int>>& graph, int cur, int n){// 找出所有从节点 0 到节点 n-1 的路径// 下标从 0 开始的if (

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

POJ 2386 Lake Counting(DFS)

题目: http://poj.org/problem?id=2386 题解: 遍历一次,遇到w,一次DFS后,与此w连接的所有w都被替换成‘ . ’,直到遍历完图中不再存在w为止,总共进行DFS的次数就是答案了。 代码: #include<stdio.h>int N,M;char map[110][110];void dfs(int x,int y){map[x][y]='