上一页 1 ··· 57 58 59 60 61 62 63 64 65 ··· 85 下一页
  2011年12月6日
摘要: UVA_10604 一开始看错题了,以为化学物质最多会有10个,所以定义不了10维的去跑,便用了类似状态压缩的方式,把化学物质的状态压缩成一个整数,然后用哈希表建立一个索引,再用记忆化搜素去处理就可以了。 之所以能这么做,关键在于总状态并不是很多,我们可以粗略的估算一下,即便有10种药品时,状态最多有(10^10)/10!,考虑到混合之后达到的状态,最多再乘个10而已,用计算器算一下,数值还是比较小的。 当然这个题目可以用6维的数组去跑,但如果药品数多了之后n维的f显然空间是开不下的,但总状态数却不是很多,所以哈希表虽然写着复杂,但多少有些适用范围的优势。 此外,要注意到这个题目A和B混... 阅读全文
posted @ 2011-12-06 13:05 Staginner 阅读(522) 评论(0) 推荐(0) 编辑
摘要: UVA_607 我们可以首先预处理出来一节课可以连着上哪些topic,并且这节课的满意度是多少。 之后用两个数组f[i]、s[i],分别表示一直上到以课程i为结尾的课时的总满意度以及上过的总课时数,动规的过程就像是跳房子,看当前位置可以跳到那个位置,就尝试去更新那个位置。#include<stdio.h>#include<string.h>#define MAXN 1010#define MAXL 510#define INF 0x3f3f3f3fint N, L, C, f[MAXN], t[MAXN], p[MAXN][MAXN], s[MAXN];int init 阅读全文
posted @ 2011-12-06 00:24 Staginner 阅读(310) 评论(0) 推荐(0) 编辑
  2011年12月5日
摘要: UVA_10118 我们可以定义f[n1][n2][n3][n4]为当四个piles分别拿到第n1、n2、n3、n4个糖果时,能够拿回家的最多的pair数,然后在状态转移的时候需要借助一个数组来记录basket的情况,可以容易想象的是,对于一个f状态,一定有唯一一个basket的状况(当然假设能取走的糖果都取走了)与之相对应。 为了实现起来更方便,我还是选用了记忆化搜索。#include<stdio.h>#include<string.h>#define MAXD 50int N, f[MAXD][MAXD][MAXD][MAXD], x[5][MAXD];int in 阅读全文
posted @ 2011-12-05 21:24 Staginner 阅读(883) 评论(0) 推荐(0) 编辑
摘要: UVA_10626 实际上我们注意到硬币的总状态不是很多,约是500*100*50(当然这么说并不准确,后面会再算),所以我们可以把硬币的组合形式看成一个状态。 剩下的问题就是如何转移状态,我们细算一下,发现花钱的策略不过这么几种,如果再分细一些,可以先分成有找零的和没找零的:①8个1分的;②3个1分的和1个5分的;③2个5分的找回2个1分的;④一个10分的找回2个1分的;⑤3个1分的和1个10分的找回1个5分的。其余的可能也有,但一定不会比上面五种决策更优。 显然递推是不好搞的,所以就不妨记忆化搜索吧。但注意到,我们按上面的策略花钱时,有些硬币是会增加的,所以我们要把上限算好。首先,③... 阅读全文
posted @ 2011-12-05 20:35 Staginner 阅读(575) 评论(0) 推荐(0) 编辑
摘要: UVA_10558 这个题目的意思是对于选定的streets,然我们选定A个avenues,使得它们划分出的选区的个数尽可能多,其中1和100是必须要选的。所谓的选区具备两个条件:①必须是横竖线所包围的一个矩形,且这个矩形内部没有横竖线;②矩形内至少包含一个neighborhood。 之后只要首先预处理出对于当前所画的竖线的条件下,如果画两条横线i、j(i<j)之间所构成的选区的数量s[i][j]。令f[i][j]表示当前选第i条横线时选在在第j条avenue上面时i下方的选区的总数,那么f[i][j]=max{f[i-1][k]+s[k][j]}。 另外读入数据时要注意neighbor 阅读全文
posted @ 2011-12-05 14:54 Staginner 阅读(396) 评论(0) 推荐(0) 编辑
  2011年12月4日
摘要: UVA_662 首先我们考虑区间[i,j]内如果建一个餐馆应该建在哪个位置,比较容易证明应该是建在中间的位置,如果是偶数个元素,中间两个位置随便一个都可以。这样我们就可以预处理出区间[i,j]内建一个餐馆的最小总路程A[i][j]了。 我们可以用f[i][j]表示第i个餐馆服务到第j个位置所需的最小总路程,那么f[i][j]=min{f[i-1][k]+A[k+1][j]},其中i-1<=k<j。#include<stdio.h>#include<string.h>#define MAXD 210#define MAXK 40#define INF 0x3f 阅读全文
posted @ 2011-12-04 22:24 Staginner 阅读(423) 评论(0) 推荐(0) 编辑
摘要: UVA_10564 我们可以用f[i][j][k]表示到第i行第j个格子时路径上值得和是否可以为k,为了保证记录的路径字典序最小的,我们可以将i由大向小循环。 状态转移的思路还是很好想的,但是写起来有些蛋疼。#include<stdio.h>#include<string.h>#define MAXD 50#define MAXS 520int N, S, f[MAXD][MAXD][MAXS], p[MAXD][MAXD][MAXS], num[MAXD], a[MAXD][MAXD];long long int d[MAXD][MAXD][MAXS];int ini 阅读全文
posted @ 2011-12-04 17:31 Staginner 阅读(451) 评论(0) 推荐(0) 编辑
摘要: UVA_10635 这个题目显然用n^2的最长公共子序列的算法会超时,后来看了别人的解题报告发现,原来最长公共子序列可以转化成最长上升子序列的问题,然后用最长上升子序列的nlogn的算法求解。 但这个方法要求任意一个字符在两序列中出现的频率都要比较低,因为转化成最长上升子序列的算法的最坏复杂度是n^2log(n^2)。而这个题目恰好每个数字最多只在两序列中各出现一次,所以就可以达到nlogn的复杂度了。#include<stdio.h>#include<string.h>#define MAXD 70000int N, P, Q, s[MAXD], r[MAXD];vo 阅读全文
posted @ 2011-12-04 17:04 Staginner 阅读(829) 评论(5) 推荐(0) 编辑
  2011年12月2日
摘要: UVA_10911 这个题目关键在于对分组状态的表示,看了别人的解题报告后发现,由于N很小,所以可以用一个整数的二进制来表示分组状态,该位置为1则代表该队员还未分组,状态转移就是枚举分组的策略就可以了。 个人感觉用记忆化搜索应该比较好实现一些。#include<stdio.h>#include<string.h>#include<math.h>#define MAXD 70000#define MAXN 20#define INF 1000000000int N;double x[MAXN], y[MAXN], f[MAXD];char b[30];doub 阅读全文
posted @ 2011-12-02 16:44 Staginner 阅读(516) 评论(0) 推荐(0) 编辑
摘要: UVA_11151 状态转移方程为:①b[i]==b[j],f[i][j]=f[i+1][j-1]+(i==j?1:2);②b[i]!=b[j],f[i][j]=max{f[i+1][j],f[i][j-1]}。#include<stdio.h>#include<string.h>#define MAXD 1010int N, f[MAXD][MAXD];char b[MAXD];void solve(){ int i, j, k; gets(b); N = strlen(b); memset(f, 0, sizeof(f)); for(k = 0; k < N; 阅读全文
posted @ 2011-12-02 14:07 Staginner 阅读(391) 评论(0) 推荐(0) 编辑
上一页 1 ··· 57 58 59 60 61 62 63 64 65 ··· 85 下一页