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的最少货币数. 解法 依 ...
随机推荐
- Spring(2) --Bean相关
你对Spring中的bean了解吗?都有哪些作用域(Scope)? Spring 官方文档对 bean 的解释是: In Spring, the objects that form the backb ...
- fastjsion反序列化漏洞渗透测试笔记
本文原创地址:https://www.cnblogs.com/yunmuq/p/14268028.html 一.背景 fastjsion是阿里的开源Java工具:https://github.com/ ...
- 计算机考研复试 A+B
题目描述 读入两个小于100的正整数A和B,计算A+B. 需要注意的是:A和B的每一位数字由对应的英文单词给出. 输入描述: 测试输入包含若干测试用例,每个测试用例占一行,格式为"A + B ...
- +load和+initialize方法调用时机
一.+load方法什么时候调用 +load方法会在runtime加载类.分类时调用(程序运行起来会先去加载调用+load 跟你引用没有引用其头文件没有关系).每个类.分类的+load,在程序运行过程中 ...
- ABAP中SQL语句,指定索引(oracle)
①常用的两种方法: 1.指定使用全表扫描:%_HINTS ORACLE 'FULL(table_name)' 表示扫描整个表 2.指定索引:%_HINTS ORACLE 'INDEX("ta ...
- 宝塔的url计划任务
to通过url访问 就像访问你的网站一样 然后控制器/方法里面写你要做的操作 就可以了 ,简单的一批
- Java基础复习2
三目运算符 语法:条件判断?表达式1:表达式2; 如果条件判断成立则获取值1否则获取值2 public class demo1{ public static void main(String[ ...
- Java流程控制与Scanner类的使用
Java流程控制与Scanner类的使用 Scanner类 Scanner类可以使程序接受键盘输入,实现人机交互 一个完整的Scanner的使用例子: //创建一个扫描器对象,用于接收键盘数据 Sca ...
- 扩展:Flash消息
扩展:Flash消息 flash存值之后只能取一次 from flask import Flask,render_template,flash,get_flashed_messages,session ...
- vue原生文件上传,可以多文件上传
1.单文件上传 <template> <div> <label for="fileInput"> <i aria-hidden=" ...