题目链接:http://219.244.176.199/JudgeOnline/problem.php?id=1213

这是这次微软实习面试的一道题,当时只相出了一个2n的做法,面试官让我优化成n的做法。不过当时没想出来,最后面试官提示到了最后才恍然大悟。

题目大意就是在一个环上有n个加油站,已知第i个加油站可以提供ai的油量,从第i个加油站到第i+1个加油站需要消耗bi的油量。(当i为n时,则表示n到1的油量)

问:是否能从某个加油站出发,绕环一圈回到这个加油站?(当途中到达某个加油站时的油量小于0则不可)。

首先可以设f(i) = a(i)-b(i),然后就可以转换成,在某个点出发回到这个点的过程中f的sum值恒大于等于0。然后就联系到最大子序列和,如果从最大子序列的起点处出发都不能绕一圈,那么显然任何位置都不行,因为任何位置出发经过最大子序列时,必然sum值小于最大子序列和,这样的话后面必然某处会出现小于0的情况。不然的话,这个位置就能构成更大的子序列,就矛盾了。

于是,我需要计算出环上的最大子序列,我想到的方法便是倍长一下,然后再求,于是就变成了2n的做法。代码中可以稍微优化一下就不需要f数组了。

关于O(n)的做法,其实也挺好想的,不过当时面试的时候,一紧张就思维混乱了。

首先如果从某个i出发,到j的时候sum(i, j)小于0了。那么[i ,j]间所有的点k出发到j处的sum(k, j)都会小于0,因为i能到k,自然sum(i, k)大于等于0,而sum(i, j) = sum(i, k-1)+sum(k, j),必然sum(k, j)要更小一点。那么[i, j]间的点都可以排除了。于是可以直接从0点出发绕一圈,遇到i不行,就继续从i+1出发,直到能跑完或者跑到n的位置处。

代码(n的做法):

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long using namespace std; const int maxN = ;
int n, a[maxN], b[maxN]; void input()
{
for (int i = ; i < n; ++i) scanf("%d", &a[i]);
for (int i = ; i < n; ++i) scanf("%d", &b[i]);
} void work()
{
int rest;
bool flag;
for (int i = ; i < n; ++i)
{
flag = true;
rest = ;
int j;
for (j = ; j < n; ++j)
{
if (rest < )
{
flag = false;
break;
}
rest += a[(i+j)%n]-b[(i+j)%n];
}
if (flag && rest >= )
{
printf("Yes\n");
return;
}
else i = min(i+j, n);
}
printf("No\n");
} int main()
{
//freopen("test2.in", "r", stdin);
//freopen("test2.out", "w", stdout);
while (scanf("%d", &n) != EOF)
{
input();
work();
}
return ;
}

代码(2n的做法):

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long using namespace std; const int maxN = ;
int n, a[maxN], b[maxN]; void input()
{
for (int i = ; i < n; ++i) scanf("%d", &a[i]);
for (int i = ; i < n; ++i) scanf("%d", &b[i]);
} void work()
{
int maxFrom, maxSum = ;
int from = , sum = , len = *n-;
for (int i = ; i < len; ++i)
{
if (sum >= )
{
sum += a[i%n]-b[i%n];
if (sum > maxSum)
{
maxSum = sum;
maxFrom = from;
}
}
else
{
sum = a[i%n]-b[i%n];
from = i%n;
}
}
sum = ;
for (int i = ; i < n; ++i)
{
if (sum < )
{
printf("No\n");
return;
}
sum += a[(maxFrom+i)%n]-b[(maxFrom+i)%n];
}
if (sum >= ) printf("Yes\n");
else printf("No\n");
} int main()
{
//freopen("test.in", "r", stdin);
//freopen("test2.out", "w", stdout);
while (scanf("%d", &n) != EOF)
{
input();
work();
}
return ;
}

ACM学习历程—SNNUOJ1213 加油站问题(动态规划 || 数学)的更多相关文章

  1. ACM学习历程—HDU 5512 Pagodas(数学)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5512 学习菊苣的博客,只粘链接,不粘题目描述了. 题目大意就是给了初始的集合{a, b},然后取集合里 ...

  2. ACM学习历程—HDU5586 Sum(动态规划)(BestCoder Round #64 (div.2) 1002)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5586 题目大意就是把一段序列里面的数替换成f(x),然后让总和最大. 首先可以计算出初始的总和,以及每 ...

  3. ACM学习历程—HDU 5073 Galaxy(数学)

    Description Good news for us: to release the financial pressure, the government started selling gala ...

  4. ACM学习历程—FZU2191完美的数字(数学)

    Description Bob是个很喜欢数字的孩子,现在他正在研究一个与数字相关的题目,我们知道一个数字的完美度是 把这个数字分解成三个整数相乘A*A*B(0<A<=B)的方法数,例如数字 ...

  5. ACM学习历程——POJ1260 Pearls(动态规划)

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...

  6. ACM学习历程—HDU2476 String painter(动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...

  7. ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...

  8. ACM学习历程—Hihocoder 1290 Demo Day(动态规划)

    http://hihocoder.com/problemset/problem/1290 这题是这次微软笔试的第三题,过的人比第一题少一点,这题一眼看过去就是动态规划,不过转移方程貌似不是很简单,调试 ...

  9. ACM学习历程—HDU5587 Array(数学 && 二分 && 记忆化 || 数位DP)(BestCoder Round #64 (div.2) 1003)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5587 题目大意就是初始有一个1,然后每次操作都是先在序列后面添加一个0,然后把原序列添加到0后面,然后 ...

随机推荐

  1. iOS 事件响应者链的学习(也有叫 UI连锁链)

    当发生事件响应的时候,必须知道由谁来响应事件.在iOS中,由响应链来对事件进行响应,所有的事件响应的类都是继承于UIResponder的子类,响应链是一个由不同对象组成的层次结构,其中每个对象将依次获 ...

  2. 如何选择合适的Linux系统进行桌面程序开发?

    32 or 64 ? 众所周知,64位的Windows系统可以近乎完美地运行32位的应用程序,微软出于商业考虑做了这样一个兼容层.而Linux系统则划分的很清楚,默认情况下64位的Linux系统无法运 ...

  3. bootstrap table 复选框使用

    var columns = [ { field : 'checked', checkbox: true, align: 'center', valign: 'middle', formatter:fu ...

  4. cookie的路径和域

    1.Cookie的路径介绍 我们知道Cookie 的属性有很多,其中有一个属性是路径path.有些人认为Cookie 的路径指的是Cookie 在客户端的保存路径,其实并不是.Cookie 的路径是相 ...

  5. 大数据架构之:Spark

    Spark是UC Berkeley AMP 实验室基于map reduce算法实现的分布式计算框架,输出和结果保存在内存中,不需要频繁读写HDFS,数据处理效率更高Spark适用于近线或准实时.数据挖 ...

  6. PHP常用函数的归纳

    //===============================时间日期=============================== //y返回年最后两位,Y年四位数,m月份数字,M月份英文.d月 ...

  7. uboot无法引导uImage错误及其解决方法

    先编译友善提供的linux内核: make ARCH=arm mini2440_defconfigmake CROSS_COMPILE=arm-linux- uImage 在arch/arm/boot ...

  8. java深入探究10-文件上传组件FileUpload,邮件开发

    1.文件上传组件FileUpload 1)java提供了文件上传的工具包 需要引入:commons-fileupload-1.2.1.jar(文件上床组件核心包) commons-oi-1.4(封装了 ...

  9. HDU 5925 离散化

    东北赛的一道二等奖题 当时学长想了一个dfs的解法并且通过了 那时自己也有一个bfs的解法没有拿出来 一直没有机会和时ji间xing来验证对错 昨天和队友谈离散化的时候想到了 于是用当时的思路做了一下 ...

  10. windows 10系统更新失败的解决办法

    最近遇到一个问题,系统总是自动下载一个更新,看样子是个补丁吧,但是每次提醒重新启动以安装更新,但每次又安装失败,回退.就这样,下载,重启,安装失败,下载......一直循环,搞得都不敢关机了,因为这样 ...