I and OI
Past...
摘要: 题意:有N头奶牛,D种疾病,已知每头奶牛都得了哪几种疾病.现在要选出尽可能多的奶牛,使得这些奶牛所带的疾病种类不大于K种,问最多能选几只.分析:D<=15,N<=1000,考虑暴力枚举疾病种类的组合,O(N)求出可以入选的奶牛数.因为有K的限制,枚举的复杂度最多为C(D,D/2)只有6000多.位运算优化下,居然79MS.code:var dis:array[0..1001] of longint; n,d,k,i,j,l,di,tmp,ans:longint; function lowbit(x:longint):longint; begin exit(x and (x xor 阅读全文
posted @ 2011-08-12 17:32 exponent 阅读(204) 评论(0) 推荐(0) 编辑
摘要: 题意:奶牛们要用K个不同类型的石头建太空电梯.每一种石头的高度为Hi,数量为Ci,且不能放在高于Ai的地方,求最高能建多高的太空电梯.分析:多重背包,数组标记.显然将ai小的放在下面会更优.所以先排序.code:const maxh=41000;var cnt:array[0..maxh] of longint; h,a,c:array[0..401] of longint; f:array[0..maxh] of boolean; n,i,j,k,tmp,ans:longint; procedure swap(var a,b:longint); var tmp:longint; begin 阅读全文
posted @ 2011-08-12 17:16 exponent 阅读(588) 评论(0) 推荐(0) 编辑
摘要: 题意:给出N个递增的数ai,M个递减的数bi.求是否存在一对ai,bj使得ai+bj=10000.分析:N<=50000,N^2效率一定不行了.看到a,b数列均单调,这可以加速.设置一个指针i指向a,j指向b.初始i=1,j=1.若ai+bj>10000,那么肯定bj+ai'(i'>i)都不等于10000,因为ai递增.所以j=j+1.同理,若ai+bj<10000,i=i+1.这个方法很有用,要记下.code(无聊地写了C++):#include<iostream>using namespace std;int a[51000],b[510 阅读全文
posted @ 2011-08-12 16:55 exponent 阅读(411) 评论(0) 推荐(0) 编辑
摘要: 题意:给出N个数(N<=10000),求是否可以找到连续的若干个数,使得他们的和为N的倍数.分析:首先根据抽屉原理,这个方案一定存在.边读边做,记录1~i的和模N的余数,如果这个数出现过,那么就可以输出方案了.code(0MS):var a,sum,bool:array[0..10001] of longint; n,i:longint; procedure print(l,r:longint); var o:longint; begin writeln(r-l+1); for o:=l to r do writeln(a[o]); halt; end;begin readln(n); 阅读全文
posted @ 2011-08-12 16:47 exponent 阅读(291) 评论(0) 推荐(0) 编辑
摘要: 题意:给出一个带权矩阵,一开始人在第1行,只能向下,左,右三个方向走,走到每一个点(i,j)都要支付a[i,j]的费用,求一条从第1行到第n行的最小费用路径.分析:DP,f[i,j]表示到(i,j)时的最优值.f[i,j]=min(f[i-1,j],f[i,j+1],f[i,j-1]).用d[i,j]记录走的方向.注意更新顺序.code:const oo=2100000000;var f,cost,d:array[0..110,0..510] of longint; res:array[0..50000] of longint; up,left,right,ans:longint; n,m,i 阅读全文
posted @ 2011-08-12 16:37 exponent 阅读(468) 评论(0) 推荐(0) 编辑
摘要: 题意:给出一个无向图,求一条1~2的路径使得路径上的最大边权最小.分析:dijkstra变形,将更新距离的过程改为取最大值即可.code:const maxn=201;var d:array[0..maxn,0..maxn] of extended; x,y:array[0..maxn] of longint; v:array[0..maxn] of boolean; n,s,t,i,j,p,casenum:longint; minx:extended; function calc(a,b:longint):extended; begin calc:=sqrt(sqr(x[a]-x[b])+s 阅读全文
posted @ 2011-08-12 16:31 exponent 阅读(1128) 评论(0) 推荐(0) 编辑
摘要: 题意:给出N个数,求形成的N^2对数的差的绝对值之和.(N<=10000)分析:N^2做肯定不行.我们看ai这个数与其他数对答案的贡献.sum=∑|ai-aj|.去掉绝对值,如果有k个数比ai小,那么ai为sum贡献了k个+ai,n-k-1个-ai.然后算法就清晰了,排序,O(N)地扫一遍统计答案.code:var a:array[0..10001] of longint; n,i,j:longint; ans,now:int64; procedure sort(l,r:longint); var i,j,mid,temp:longint; begin i:=l; j:=r; mid:= 阅读全文
posted @ 2011-08-12 16:26 exponent 阅读(508) 评论(0) 推荐(0) 编辑
摘要: 题意:给出N头牛,每头牛有若干个喜欢的点(x,y).求一个方案,使得每头牛都可以在自己喜欢的位置上,且将这N头牛以1~N的顺序连成一个环(如1-2-3-4-1)所花费的绳子长度最短.分析:DP,f[i,j]表示将第i头牛绑在它喜欢的第j个位置的最优值.因为要首尾相连,干脆就枚举1号牛绑的位置.code:type cow=record x,y:longint;end;const oo=100000000;var f:array[0..101,0..41] of extended; c:array[0..101,0..41] of cow; p:array[0..101] of longint; 阅读全文
posted @ 2011-08-12 16:11 exponent 阅读(248) 评论(0) 推荐(0) 编辑
摘要: 题意:给出一个带权矩阵,一条合法路径应满足下列条件:1.跳跃方式为中国象棋中的马步.2.每步只能跳往权值比上一步大的格子.现在求最长的合法路径,多种方案时输出字典序最小的.分析:POJ1088滑雪的改进版.用f[i,j]表示从(i,j)出发的最长路径.记忆化搜索,同时更新最优方案.code:type recnode=record x,y:longint;end;var fx:array[1..8,0..1] of longint=((-2,-1),(-1,-2),(1,-2),(2,-1) ,(2,1),(1,2),(-1,2),(-2,1)); f,num:array[0..400,0..4 阅读全文
posted @ 2011-08-12 16:02 exponent 阅读(272) 评论(0) 推荐(0) 编辑
摘要: 题意:给定一个矩阵,从左上角到右下角,使走过的路径中数字的最大值最小值之差最小,问差最小是多少.分析:二分枚举差值,枚举下界,bfs判定可行性.code:type mapnode=record x,y:longint;end;var fx:array[1..4,0..1] of longint=((0,1),(0,-1),(-1,0),(1,0)); tall:array[0..101,0..101] of longint; vis:array[0..101,0..101] of boolean; q:array[0..10000] of mapnode; n,i,j,l,r,mid,maxh 阅读全文
posted @ 2011-08-12 15:54 exponent 阅读(239) 评论(0) 推荐(0) 编辑
摘要: 题意:给出N(N<=40)根木棍,每根长度为Li(Li<=40),要用完所有的木棍构成面积最大的三角形,求最大面积.分析:用can[i,j,k]表示用前i根木棍,组成两条长为j,k的长木棍是否可能.can[i,j,k]=can[i,j,k] or can[i-1,j-l[i],k] or can[i-1,j,k-l[i]] or can[i-1,j,k].最后枚举两条边,求出第三条边,用海伦公式求出面积即可.这是比较水的算法,跑了844MS..code:var can:array[0..40,0..800,0..800] of boolean; l:array[0..41] of 阅读全文
posted @ 2011-08-12 15:48 exponent 阅读(508) 评论(0) 推荐(0) 编辑
摘要: 题意:给出一棵树,问最少切断几条边可以得到有p个结点的子树.分析:明显的树形DP.f[i,j]表示以第i个节点为根的子树保留j个节点最少需要去掉几条边.f[i,j]=min{f[i,j-k]+f[s,k]-2} (s是i的儿子)ans=min{f[i,p]}code:type edge=record v,n:longint;end;const root=1; oo=10000;var e:array[0..400] of edge; vis:array[0..200] of boolean; h,s:array[0..200] of longint; t,f:array[0..200,0..2 阅读全文
posted @ 2011-08-12 15:40 exponent 阅读(1164) 评论(0) 推荐(0) 编辑
摘要: 题意:有n个任务,第i个任务需要时间ti来完成,并且第i个任务必须在它前面的某些任务完成之后才能开始.给你任务信息,问你最短需要多少时间来完成任务.分析:题目给出的数据已经拓扑有序了,直接DP.f[i]表示第i个任务完成的最短时间,f[i]=max{f[j]}+ti (j必须在i之前完成)ans=max{f[i]}.code:var f:array[0..10001] of longint; n,i,j,k,t,p,ans,tmp:longint;begin readln(n); for i:=1 to n do begin read(t); read(k); tmp:=0; for j:=1 阅读全文
posted @ 2011-08-12 15:35 exponent 阅读(286) 评论(0) 推荐(0) 编辑