UVa
文章平均质量分 60
亚N程
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
UVa:10074 Take the Land
不小心瞄到题目提示,于是联想到之前做过的求最大子矩阵和的那道题。 这道题很类似,但是有些不同的是,可以计算的只有是0的矩阵,如果出现1就不能计算。所以在求每个一维数组和的时候要保证序列中没有1。如果在原O(n^3)的算法上再判断就变成O(n^4)了。这里我用了空间换取时间的策略,另开一个三维数组me[i][j][k]记录第i行第j到k个元素之间是否包含1。 这样最后还是O(n^原创 2013-09-04 12:29:41 · 1061 阅读 · 0 评论 -
UVa:825 Walking on the Safe Side
网速不给力CE1次,输出间忘了空行WA1次。 状态转移方程:map[i][j]=map[i][j+1]+map[i+1][j] 我是按右下角到左上角的顺序,每次沿左下角连右上角的对角线计算。最后由子问题组合成原问题的解即map[1][1]. #include #include #include #include using namespace std;原创 2013-09-03 23:04:53 · 691 阅读 · 0 评论 -
UVa:11407 Squares
简单动规。 dp[i]表示i的最小表示数目。如果i可以被开方 dp[i]=1;否则dp[i]=min{dp[j]+dp[i-j]}(0 #include #include #include #include #include #define MAXN 10000using namespace std;int dp[MAXN+1];int原创 2013-09-01 10:15:27 · 638 阅读 · 0 评论 -
UVa:116 Unidirectional TSP
开始开了几个1000*1000的数组TLE到死,后来改小以后居然跑了个rank56.。。 确实是一道比较简单的动规。状态转移方程是dp[i][j]=min{dp[i-1][j+1],dp[i][j+1],dp[i+1][j+1]}。 由于要输出字典序最小的情况所以当相等的时候要考虑一下三种情况的优先级。 不是很会写所以将一行和两行的情况单独处理了。 最后写了一百原创 2013-09-01 08:44:22 · 749 阅读 · 0 评论 -
UVa:311 Packets
填满的时候:一个6*6=一个5*5+十一个1*1=一个4*4+五个2*2=4个3*3=9个2*2=36个1*1填不满的时候类似。。。 一个2*2=四个1*1.它俩之间的转换比较常用。一开始转换的时候忘了乘以4,WA了N次。。 每次尽量先用大的,大的不足再用小的。 #include #include #include #include using原创 2013-08-22 13:24:56 · 711 阅读 · 0 评论 -
UVa:147 Dollars
#include #include #include using namespace std;int main(){ long long dp[12][6005]={0}; int m[]={0,1,2,4,10,20,40,100,200,400,1000,2000}; dp[0][0]=1; for(int i=1;i原创 2013-08-18 17:53:07 · 615 阅读 · 0 评论 -
UVa:357 Let Me Count The Ways
状态转移方程是dp[i][j]=dp[i-1][j]+dp[i][j-m[i]];d[i][j]是使用前i种金币可以组合成j钱的种数。它包括两种情况,一种是不使用第i种金币的时候,另一种是使用第i种金币的时候。 可以直接用一维数组,前提是不打印最优解。 #include #include #include using namespace std;i原创 2013-08-18 17:51:42 · 711 阅读 · 0 评论 -
UVa:10066 The Twin Towers
#include#include#include#include#includeusing namespace std;int main(){ int n,m,count=0; while(scanf("%d%d",&n,&m)&&!(!n&&!m)) { int x[105]={0},y[105]={0};原创 2013-08-12 20:22:44 · 657 阅读 · 0 评论 -
UVa:10130 SuperSale
经典的01背包问题。只不过是把每个背包可容纳的最大价值加起来罢了。 #include #include #include #include using namespace std;int main(){ int T; scanf("%d",&T); while(T--) { int N,w[1005],p原创 2013-08-11 14:37:13 · 709 阅读 · 0 评论 -
UVa:10583 Ubiquitous Religions
并查集。最后要求输出合并之后集合的个数。 原本我是找到每个结点的祖先并统计个数这样来做的。这里说一种更为高端的做法。 技巧体现在find函数的写法上。将每个集合初始化为-1.表明为根节点,查询时则返回自身。同时压缩路径。最后只统计-1的个数即可。 #include #include #include #include using namespace原创 2013-08-09 15:02:18 · 834 阅读 · 0 评论 -
UVa:369 Combinations
#include#include#include#include#includeusing namespace std;long long C(int n,int k){ long double s=1.0; for(long double i=0.0;i { s*=(n-i)/(k-i); }原创 2013-07-26 12:19:07 · 956 阅读 · 0 评论 -
UVa:10020 Minimal coverage
区间覆盖问题,书上有分析但还是用了好久才AC掉。用贪心法,依据每条线段的起点排序,依次扫描在线段起点小于等于区间左端点(初始为0)的前提下,选取有效长度最长(即线段终点最大)的那条线段的终点作为新区间的起点,然后继续像开始那样扫描直至所得线段终点大于等于区间右端点。线段尽量长才能保证覆盖区间尽量大,才使得所用线段尽量少,这是贪心的关键。我写的代码中有一些细节需要注意。比原创 2013-07-27 12:04:09 · 751 阅读 · 0 评论 -
UVa:11462 Age Sort
水题,用计数排序即可。 算法介绍计数排序是一个类似于桶排序的排序算法,其优势是对已知数量范围的数组进行排序。它创建一个长度为这个数据范围的数组C,C中每个元素记录要排序数组中对应记录的出现个数。计数排序是一个非基于比较的线性时间排序算法。它对输入的数据有附加的限制条件:1、输入的线性表的元素属于有限偏序集S;2、设输入的线性表的长度为n,|S|=k(表示集合S中元素的总原创 2013-08-07 21:02:49 · 662 阅读 · 0 评论 -
UVa:993 Product of digits
很简单的一道题,只要将这个数从9到2挨个除,能除尽的就存下来最后倒序输出就可以了。因为要求输出最小值,所以每次都是从最大的个位数9开始寻找因子,可以保证结果位数最短而且从大到小有序。最后倒序输出就是最小结果了。如果这个数本身就小于10那么答案就是它自身了。 #include #include #include using namespace std;int main原创 2013-08-03 16:21:18 · 679 阅读 · 0 评论 -
UVa:714 Copying Books .
最大值最小化的问题,卡了两天才做出来。入门经典上有分析,但是只提供了求最小的最大值的思路。具体方法是在某区间上用二分法猜数字,最后猜的一个数x是使得【将输入数列划分成m个连续子序列使得所有S(i)均不超过x】成立的最小x,这就是最小的最大值。这里二分的并非数组,而是一种很抽象的形式。还要好好领会。二分的区间自然是数列的最大值到数列总和。 之后的如何切分是让我最困原创 2013-07-31 14:21:54 · 765 阅读 · 0 评论 -
UVa:481 What Goes Up
LIS+打印最优解。O(n^2)会超时,所以用O(nlgn)的算法。a[]表示原序列;dp[i]表示以dp[i]为尾元素的最长递增序列长度为i;dpos[i]表示a[i]在dp[]中的下标;pre[i]表示以a[i]为尾元素的最长递增序列中a[i]之前的元素下标。最后递归打印pre[]即可。 #include #include #include #include #原创 2013-09-11 09:30:29 · 1243 阅读 · 0 评论 -
UVa:10684 The jackpot
DP有点刷不动了,只好再看看书和资料补一补。本着日A一题的原则,今天刷了一道水题。最大子段和的问题。 #include #include #include #include #include using namespace std;int main(){ int n,a; while(scanf("%d",&n)&&n) {原创 2013-09-09 22:40:47 · 1562 阅读 · 0 评论 -
UVa:10404 Bachet's Game
博弈论上的动态规划,1Y。 #include #include #include #include #include using namespace std;bool dp[1000005];int a[15];int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF)原创 2013-09-07 09:28:53 · 800 阅读 · 0 评论 -
UVa:437 The Tower of Babylon
感觉UVA上的入门经典DP这块不是LCS就是LIS。这个题是LIS,1Y。 没有想太多,对于每次输入的x,y,z,我都构造了3!=6种的形态。分别依照x,y,z降序排序,然后再进行LIS动规。 #include #include #include #include #include using namespace std;struct B原创 2013-09-02 17:40:09 · 706 阅读 · 0 评论 -
UVa:531 Compromise
还是LCS的题,只不过单个字符换成了单词。一开始没有注意多组测试数据WA了1次。 递归实现输出路径。 #include #include #include #include #include using namespace std;string a[101],b[101];int dp[101][101],path[101][101];bool原创 2013-09-02 15:35:34 · 789 阅读 · 0 评论 -
UVa:10465 Homer Simpson
完全背包+贪心。1Y。利用完全背包的思路求出吃汉堡所用的最大时间。然后在构造最优解的时候每次先考虑用时少的汉堡,这样可以保证吃的汉堡尽量多。 #include #include #include #include #include using namespace std;int dp[3][10005];int main(){ int原创 2013-09-02 14:44:48 · 658 阅读 · 0 评论 -
UVa:348 Optimal Array Multiplication Sequence
早就做出来了一直存在没发。经典的区间DP。时间复杂度O(n^3)三重循环分别枚举长度起点切点。打印路径的思路出自算法导论。 #include #include #include #include using namespace std;int s[20][20]= {0};void Print_optimal_parens(int i,int j)原创 2013-09-02 10:40:24 · 654 阅读 · 0 评论 -
UVa:103 Stacking Boxes
1Y.做完10131 Is Bigger Smarter?以后才知道是个LIS的题。这个题跟那个很相似。不多说了。 #include #include #include #include #include using namespace std;struct Box{ int num,d[12];};Box p[32];int dp原创 2013-09-01 23:36:38 · 676 阅读 · 0 评论 -
UVa:11078 Open Credit System
这里我是用分治法做的。方法有点像算法导论上求最大连续数组和。求Ai-Aj最大值。有三种情况。1.Ai Aj都位于左段区间2.Ai Aj都位于右段区间3.Ai位于左段区间,Aj位于右段区间。那么如果要使Ai-Aj最大,Ai肯定是左段区间的最大值,Aj是右段区间的最小值。1和2都是原问题的更小规模,可以分治处理。3不是,我们可以把它视作合并的过程。#incl原创 2013-08-16 22:36:38 · 714 阅读 · 0 评论 -
UVa:10954 Add All
其实是一个贪心的题目。每次要相加的是数组里面最小的两个数,得到的结果要存到这个数组里面(原来两个数去掉),以供下次使用。直至将所有数都加过,而每次两数相加之和就是最终所求结果。为什么每次都是要最小的相加呢?COST之和最小要求每个COST都要尽量的小,那么组成COST的每部分(原数组中的数或者后来相加所得COST)也要尽量的小。要求向数组中加入新的数再使数组保持有序,显然要原创 2013-07-27 12:06:30 · 738 阅读 · 0 评论 -
UVa:10714 Ants
简单题。最短的好想,都向自己临近的一端走就行了。最长的呢?仔细一想就会发现即使两只蚂蚁相遇了,反向了,跟原来的情况还是一样的,所以最长的情况就是都向自己临着远的一端走。求所有蚂蚁掉出的时间所以只需要算走得最长的那只蚂蚁用的时间即可。看起来很复杂,其实连数组都可以不用开。。 #include #include #include using namesp原创 2013-08-08 13:45:26 · 677 阅读 · 0 评论 -
UVa:10132 File Fragmentation
其实想明白了还是道挺简单的题。 最大的碎片跟最小的组合中一定有原文件。次最大和次最小的碎片的组合中也一定有原文件。很明显两个组合中相同的那个文件就是原文件。因为没有完全相同的碎片,所以即使最大的和最小的碎片都有两个,这个思路也是完全可行的。 算是贪心吧,这是解决问题的一个很关键的点。 当然如果一共就两块碎片那就不用麻烦了,它俩的组合一定就是答案。 今天重做这原创 2013-08-03 15:48:33 · 675 阅读 · 0 评论 -
UVa:10154 Weights and Measures
一度把题目想简单,WA1次。后来没有想清楚第i只龟不能承受的情况又WA了一次。 如果用一维数组保存状态的话,过程是不满足无后效性的(这里我居然想到了),所以需要加维来消去后效性。想到了两种加维的办法。1.dp【i】【j】表示第i只龟承重为j时所载最大龟数。 质量上限j题目并未给出,估计很大,数组很难存下。2.dp【i】【j】表示第i只龟承载j只龟时所承受的最小质量。原创 2013-09-05 23:18:44 · 976 阅读 · 0 评论 -
UVa:10564 Paths through the Hourglass
dp[i][j][k]表示到达第i层第j个格子值为k时的路径条数。由已知的dp[i][j][k]可以递推出新一层的dp,而因为它要求输出一条最靠左的路径,所以由下向上递推比较好。上层的dp[][][]可以由下一层已经求出的两个相邻的dp[][][]求出。 这样路径数组path[i][j][k]表示到第i层第j个格子值为k是由左下或者右下方向而来。另外当从左下或者右下到达(i,j原创 2013-09-08 22:00:04 · 672 阅读 · 0 评论 -
UVa:836 Largest Submatrix
1Y。和上一道10074基本是一样的题。只不过要用字符来读。 #include #include #include #include using namespace std;bool a[105][105],me[105][105][105];int s[105][105];int main(){ int T; scanf("%原创 2013-09-05 09:12:18 · 839 阅读 · 0 评论 -
UVa:10285 Longest Run on a Snowboard
1Y.状态转移方程是dp【i】【j】=max{dp【x】【y】}+1.( x,y)表示(i,j)上下左右四个位置中比p(i,j)低的坐标。 先解决子问题再组合成原问题的解。因此需要根据每个点的高度排序然后从小到大解决,当然也要记录下每个点的坐标对应到原位置。 #include #include #include #include #inclu原创 2013-09-02 16:30:39 · 587 阅读 · 0 评论 -
UVa:11151 Longest Palindrome
最长回文串问题。因为吞键盘的getsWA了好几次。 记忆化搜索+动规。dp【i】【j】表示以i为左端点j为右端点的字符串中最长回文串长度。 #include#include#include#includeusing namespace std;char str[1005];int dp[1005][1005];int solve(int st,原创 2013-08-28 18:14:59 · 625 阅读 · 0 评论 -
UVa:10791 Minimum Sum LCM
要求集合中的元素互质,乘积为N,且和最小,输出这个和。将N开方,从中间向两边寻找,这样可以保证和最小。同时还要满足互质,也就是最大公约数是1。 递归实现。 WA了很多次。一开始没考虑到集合中每个元素都要互质的问题。比如说18,原来做法集合中元素是3,6,但其实这样最小公倍数就是6而不是18了,所以正确答案是2,9。还有开始的时候特判了两个因子相同的时候,比如说36=6*原创 2013-08-20 10:32:36 · 900 阅读 · 0 评论 -
UVa:10034 Freckles
还是最小生成树的问题。 不过这里的边需要自己求。两个循环就可以求出来。 Kruskal算法:#include #include #include #include #include #include using namespace std;int father[105];struct Edge{ int u,v; doub原创 2013-08-10 12:20:17 · 724 阅读 · 0 评论 -
UVa:10057 A mid-summer night's dream
最后的英文有点看不懂了。 最后要求输出:第一个数字为A最小的可能值为多少。第二个数字为输入中有多少个数字和 A 有相同的性质(就是能满足上述的条件者)。第三个数字为A可能有多少种可能的不同值(这些不同的数字不必印出来)。其实题很简单,纯粹考数学。可以把这些x想象成数轴上的点, |X-A|的几何意义是某点X到点A的距离,很明显对于|X1-A| + |X2-A| 这种情原创 2013-08-04 16:11:36 · 779 阅读 · 0 评论 -
UVa:10271 Chopsticks
想了一晚上加一上午,总算是给做出来了,还是1Y. 还是跟前面的几道题有些相似。dp[i][j]表示前i个客人使用第j支与第j-1支筷子作为短筷子时的烂度。很明显三元组中两只短筷子一定是相邻的,长筷子则不一定。用降序做会比较好。p[i][j]表示dp[i][j]对应状态可使用的长筷子。 状态转移方程: 如果p[i-1][j-2]>1则说明可以使用第j支与第j-1支原创 2013-09-10 21:15:26 · 923 阅读 · 0 评论 -
UVa:11003 Boxes
跟10154的差不多。有两点不同。1是可承重不包括自重,2是编号小的不能放在大的上面。 果然看题解是不好的行为,做这道题的时候又被卡住了,其实刚做了10154没几天。一直在最小承受重量这里犯糊涂。 dp[i][j] 表示使用前i个盒子组成一堆共有j个盒子的最小重量。为什么要最小呢,只有最小才能保证可以堆成盒子的数目最多。这里是相通的。dp[i][j]=min(dp[原创 2013-09-10 19:21:04 · 1531 阅读 · 0 评论 -
UVa:11137 Ingenuous Cubrency
还是统计硬币组合方式的题。之前做过好几次了。状态转移方程dp[i][j]=dp[i][j-p[i]]+dp[i-1][j];注意UVAlonglong要用lld。 #include #include #include #include #include #define MAXS 500using namespace std;int p[25];原创 2013-09-08 22:45:28 · 804 阅读 · 0 评论 -
UVa:12455 Bars
搜索题,1Y。直接暴搜,时间复杂度是O(2^n),恐怖的指数阶,因为数据量很小所以也没关系。 #include #include #include #include using namespace std;int L,n,a[25];bool solve(int i,int sum){ if(i>n) { i原创 2013-09-05 10:31:39 · 1423 阅读 · 0 评论 -
UVa:10534 Wavio Sequence
一开始用了O(n^2)的算法超时了两次,后来脑子抽了居然用升降序列相同来判答案又WA了一次。 这个题也是LIS,但是只能用O(nlgn)的算法。 一开始以为O(nlgn)只能求解整个序列的最长递增,其实不然,以p[]表示原序列,lis[]表示辅助数组,那么lis[i]表示以lis[i]结尾的最长递增序列长度是i(1到这里就完成一半了。然后就需要求以p[j]为开头的最长递减序原创 2013-09-06 13:53:08 · 827 阅读 · 0 评论
分享