C - C(换钱问题)
For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR.
You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges, and real RAB, CAB, RBA and CBA - exchange rates and commissions when exchanging A to B and B to A respectively.
Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative sum of money while making his operations.
Input
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10-2<=rate<=102, 0<=commission<=102.
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 104.
Output
Sample Input
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00
Sample Output
YES
方法1:用Bellman算法,若存在正权回路,则说明货币经转化是越来越大的,即满足题意。
所以,这道题就是在让你求回路中是否存在正权回路。
#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
int n,m,x,flag,u[220],v[220];
double y,dis[220],r1[220],c1[220],r2[220],c2[220];
void djk()
{
for(int i=1;i<n;i++)
{
int ans=0;
for(int j=1;j<=m;j++)
{
if(dis[v[j]]<(dis[u[j]]-c1[j])*r1[j])
{
dis[v[j]]=(dis[u[j]]-c1[j])*r1[j];
ans++;
}
if(dis[u[j]]<(dis[v[j]]-c2[j])*r2[j])
{
dis[u[j]]=(dis[v[j]]-c2[j])*r2[j];
ans++;
}
}
if(ans==0) break;
}
flag=0;
for(int j=1;j<=m;j++)
{
if(dis[v[j]]<(dis[u[j]]-c1[j])*r1[j])
{
flag=1;
break;
}
if(dis[u[j]]<(dis[v[j]]-c2[j])*r2[j])
{
flag=1;
break;
}
}
}
int main()
{
while(~scanf("%d%d%d%lf",&n,&m,&x,&y))
{
memset(dis,0,sizeof(dis));
dis[x]=y;
for(int i=1;i<=m;i++)
scanf("%d%d%lf%lf%lf%lf",&u[i],&v[i],&r1[i],&c1[i],&r2[i],&c2[i]);
djk();
if(flag) printf("YES\n");
else printf("NO\n");
}
}
方法2:
SPFA方法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
#define INF 0x3f3f3f
using namespace std;
typedef pair<int,int> P;
const int maxn = 1e2+10;
int n,m,s,tot;
double v;
double dis[maxn];
int head[maxn],vis[maxn];
double cost[maxn][maxn],rate[maxn][maxn];
struct node
{
int to;
double w;
int next;
} edge[maxn*maxn]; void add(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} bool SPFA(int s,double v)
{
for(int i=1; i<=n; i++)
{
dis[i] = 0;
vis[i] = 0;
}
dis[s] = v;
vis[s] = 1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i=head[x]; i!=-1; i=edge[i].next)
{
int j = edge[i].to;
if(dis[j]<(dis[x]-cost[x][j])*rate[x][j])
{
dis[j] = (dis[x]-cost[x][j])*rate[x][j];
if(dis[s]>v)
return true;
if(!vis[j])
{
q.push(j);
vis[j] = 1;
}
}
}
}
return false;
} int main()
{
while(cin>>n>>m>>s>>v)
{
int i;
memset(cost,0,sizeof(cost));
memset(rate,0,sizeof(rate));
memset(head,-1,sizeof(head));
tot = 1;
for(i=0; i<m; i++)
{
int a,b;
double cab,rab,cba,rba;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
cost[a][b] = cab;
cost[b][a] = cba;
rate[a][b] = rab;
rate[b][a] = rba;
add(a,b);
add(b,a);
}
if(SPFA(s,v))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
C - C(换钱问题)的更多相关文章
- 算法进阶面试题07——求子数组的最大异或和(前缀树)、换钱的方法数(递归改dp最全套路解说)、纸牌博弈、机器人行走问题
主要讲第五课的内容前缀树应用和第六课内容暴力递归改动态规划的最全步骤 第一题 给定一个数组,求子数组的最大异或和. 一个数组的异或和为,数组中所有的数异或起来的结果. 简单的前缀树应用 暴力方法: 先 ...
- [DP]换钱的方法数
题目三 给定数组arr, arr中所有的值都为整数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,在给定一个整数aim代表要找的钱数,求换钱有多少种方法. 解法一 --暴力递归 用0 ...
- OptimalSolution(1)--递归和动态规划(2)矩阵的最小路径和与换钱的最少货币数问题
一.矩阵的最小路径和 1 3 5 9 1 4 9 18 1 4 9 18 8 1 3 4 9 9 5 8 12 5 0 6 1 14 14 5 11 12 8 8 4 0 22 22 13 15 12 ...
- [程序员代码面试指南]递归和动态规划-换钱的方法数(DP,完全背包)
题目描述 给定arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,求组成aim的方法数. 解题思路 完全背包 和"求换钱的 ...
- 算法之Python实现 - 003 : 换钱的方法数
[题目]给定数组arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的方法数. [代码1]递归 impor ...
- 算法之Python实现 - 002 : 换钱的最少货币数补充(每种货币只能使用一次)
[题目]:给定数组arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币仅可以使用一张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数. [代码1]:时间与额 ...
- 算法之Python实现 - 001 : 换钱的最少货币数
[题目]给定数组arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数. [代码1]:时间与额外 ...
- MT【227】换钱的总数
(2012复旦)将1张面值100元的人民币全部换成面值1角,2角,5角的人民币,不同的换法有多少种? 解:即求不等式$2x+5y\le1000$的所有非负整数解的个数.由匹克公式:$S=a+\dfra ...
- [DP]换钱的最小货币数
题目一 给定数组arr,数组中有N个元素,其中所有的之都为整数且不重复.每个只代表一种面值的货币,每种面值的货币可以使用任意张,在给定一个整数aim代表要找的钱数,求组成aim的最少货币数. 解法 依 ...
随机推荐
- Linux常用命令(df&dh)
在Linux下查看磁盘空间使用情况,最常使用的就是du和df了.然而两者还是有很大区别的,有时候其输出结果甚至非常悬殊. du的工作原理 du命令会对待统计文件逐个调用fstat这个系统调用,获取文件 ...
- Django(投票程序)
Django是一个web框架,python编写的. MTV模式 Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同 -M代表模型(Model ):负责 ...
- Kali Debian 修改时区
1.KaliDebian默认读取时区文件是/etc/localtime(重建软连接,达到修改时区目的) 2./etc/localtime是个软连接,连接到时区文件/usr/share/zoneinfo ...
- 【老孟Flutter】2021 年 Flutter 官方路线图
老孟导读:这是官方公布的2021年路线图,向我们展示了2021年 Flutter 的主要工作及计划. 原文地址:https://github.com/flutter/flutter/wiki/Road ...
- MySQL中的全局锁和表级锁
全局锁和表锁 数据库锁设计的初衷是解决并发出现的一些问题.当出现并发访问的时候,数据库需要合理的控制资源的访问规则.而锁就是访问规则的重要数据结构. 根据锁的范围,分为全局锁.表级锁和行级锁三类. 全 ...
- 解压rpm文件
rpm2cpio zabbix-2.2.2-0.el6.zbx.src.rpm |cpio -div
- 【Oracle】win7安装报错
在WIN7上安装oracle 10g时,提示如下信息: 正在检查操作系统要求... 要求的结果: 5.0,5.1,5.2,6.0 之一 实际结果: 6.1 检查完成.此次检查的总体结果为: 失败 &l ...
- LeetCode897. 递增顺序查找树
题目 法一.自己 1 class Solution { 2 public: 3 vector<int>res; 4 TreeNode* increasingBST(TreeNode* ro ...
- 检查Mysql主从状态
.检查MySQL主从同步状态 #!/bin/bash USER=bak PASSWD=123456 IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e show s ...
- SP338 ROADS
题目描述 城市中有R条有向马路,n个马路连接点,通过每条马路都要花去一定费用.你现在在编号为1的连接点 ,手里有k元钱,要去n号连接点的最短路径的长度是多少?途中经过道路的花费不能超过k.注意:两个 ...