poj刷题存档(1)

poj1328

一种从没有写过的贪心。以每个点为圆心,以覆盖半径为半径作圆,计算与X轴交点,利用交点区间进行贪心。每次对区间求并集,若并集为空则更新答案,更换当前维护区间。

poj1573

直接模拟记录走过的坐标并记录是第几步走过,如果走到了曾经走过的坐标就会有环。

其实我是被初始化坑了。。。

poj2993

比较水的模拟。。。难的是读入。。。

运用正则表达式(话说这是神马。。。)。

scanf("%*[ ,]%[^,\n]",s)

嗯。。。就是这样   “*” 可以滤掉空格逗号 , 遇到逗号或换行停止读入。

poj3259

spfa判负环,某顶点入队次数超过顶点个数,一定存在负环。

poj1062

比以往的spfa维护只多了等级的限制。。。虽然维护也不太好写。。。

以物品作为顶点。

枚举(max等级 - min等级)个区间长度为 2*等级限制的区间,每次只维护等级在这个区间内的点。如果顶点1不在区间里则忽略。

记录dis[],dis[1]=0,然后从1开始做spfa,最后取min(dis[i]+cost[i])(i在区间内)更新最优值。

poj3436

运用dinic,输出路径时只要遍历所有正边,发现其流量减少就说明这条边有流经过,输出即可。

poj3274

经典的转化问题,设C[i][j] = A[i][j] - A[i][0] , hash求最远相同行的距离。

poj2503

我直接水map了。。但是注意不可以map<char*,char*>,应该把char*放入结构体重载“==”,因为指针毕竟是不可能相同的。。。

poj2513

一道比较综合的题目。

首先利用Trie将字符串hash成一个整数,然后以这些整数为顶点标号构建出一个图判断是否存在欧拉通路。

条件1:连通 利用并查集判断所有顶点的祖先是否是同一个,如果不是则不可能;

条件2:度数为奇数的顶点个数为0或2满足条件,否则不满足。

(我又忘了初始化并查集了ORZ...)

poj3347

一道貌似是计算几何的问题。。看到别人的题解恍然大悟。。。

第一步:放置正方形

对于每个新读入的正方形,维护l[i],r[i]表示第i个正方形最左端点和最右端点。

有l[i] = max(r[j] - abs(len[i]-len[j]),l[i]) (1<=j<i)  特别的l[1] = 0;每个i也初始化为0

第二步:维护可视区间

for(i = 1 ; i <= n ; ++i)
for(j = 1 ; j < i ; ++j)
{
if(S[i].len > S[j].len && S[j].r > S[i].l) S[j].r = S[i].l;
else if(S[i].len < S[j].len && S[i].l < S[j].r) S[i].l = S[j].r; 
}

 不解释。。。 

第三步:检查合法性

如果l[i]<r[i]说明能看到,输出。

poj2826

不愧是poj月赛,WA了一个下午,此所以学者不可以不深思而慎取者也。。。不要轻易做这道题啊。。。WA到吐血。。

注意遮挡和部分遮挡的情况!!fuckfuckfuckfuckfuck!

以至于用叉积判断相交已经过于平凡了。。。

poj1584

我是用求凸包上点的个数是否与原来点的个数相等来判断是否是凸多边形。

不过这道题有一个坑点。。。

有可能求出的凸包上有一条边上有若干个点

Andrew判断弹栈条件时把'='去掉。

poj1472

使用栈来实现(话说递归我居然没写出来)。

把‘begin’当作'LOOP 1'来实现。

遇到LOOP,OP入栈,遇到end建立一个新多项式,进行弹栈,依次累加上OP的多项式值,直到栈顶为LOOP,将当前的多项式乘以LOOP的系数(然后把这个"loop"弹栈),得到一个新多项式,把"OP 新多项式"压栈。

依次处理直到栈里面只有一个'OP',它的值就是答案。

输出要很小心!!切记!(比如 1*x^0之类的。。。)

poj3352

根据某大牛的题解,先对原图进行一次记录low值的dfs,low值相同的某几个点所组成的即为边-双连通分量。

然后再根据(叶子节点个数 + 1)/2的公式计算即可。

参见小U的题解。讲的非常清楚。

传送门:http://blog.csdn.net/lyy289065406/article/details/6762370

poj3308

题意是给定矩阵中的一些点,覆盖每一行、每一列都有对应的费用,求出覆盖所有点所需费用乘积的最小值。

首先乘积的最小值是不容易处理的,我们把每一个费用取自然对数,然后做最小割,答案利用exp()输出。

我们把每一行、每一列都作为顶点,把源点向每一个行点连一条流量为原费用自然对数的边,对于矩阵中每一个点都使他的行点向列点连一条流量为INF的边,把每一个列点向汇点连一条流量为原费用自然对数的边,然后要求最小割,需要跑最大流。

为什么这样是可以的呢?

假设原点与汇点能够连通(有流量),那么必然经过一条行点与列点相连的边,也就意味着这个点没有被“消灭”,反之,而求出了图的最小割,也就意味着原点与汇点不连通,即所有的点都已经被覆盖了。

精度问题需要特别注意。详情见discuss.

poj3411

简单的爆搜,利用一下位运算和适当剪枝就可以秒杀了。

发一下我的dfs代码:

void dfs(int x , int state , int now)
{
	if(x == n)
	{
		if(now < Min)
		{
			Min = now;
		}
		return;
	}
	for(int i = head[x] ; i ; i = next[i])
	{
		if(((1 << prev_city[i]) & state) != 0)
		{
			if(now + prev_cost[i] < Min && vis[end[i]])
			{
				--vis[end[i]];
				dfs(end[i] , state | (1 << end[i]) , now + prev_cost[i]);
				++vis[end[i]];
			}
		}
		else if(now + cost[i] < Min)
		{
			--vis[end[i]];
		    dfs(end[i] , state | (1 << end[i]) , now + cost[i]);
			++vis[end[i]];
		}
	}
}
vis数组用来保存当前每个节点剩余的访问次数(对于某些坑爹测点每个节点可能经过多次来换取最小费用!)

把vis初始化为N就好了,这样vis为0时证明这个节点已经访问了n次,而这是不可能的。

这样也可以0ms.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值