140705

集训第七天了。心里有些感慨


有些想家了。给家里打了电话,我想也快了把,就要回到开化了。想来,已经半年不在开化了,整整半年。


今天写了两道题,一个是poj2559,一个事poj1751

poj2559:维护一个单调栈。

如果后期有空我会贴点报告。现在只贴个代码把。


核心思想在于,利用单调栈,找出每个pop的元素的最大可拓展边界,把复杂度从o(n^2)弄到o(n)

代码如下:

#include <cstdio>
#include <iostream>
using namespace std;
#define MAXSIZE 1000000
/*
 * poj2559,维护一个单调栈就可以了。
 * 第一次用栈,逻辑不是很清楚
 * 大概这样:每次弹出元素的时候,计算这个元素形成的面积。跟最值比较。
 * 再写点,,之前弄懂后来又忘了。
 * 就是,每次出栈,栈顶元素肯定是不比他在栈里下面那个元素低的,这是他能拓展的左边最长的地方
 * 既然出栈,必然新的元素比栈顶元素低,因为出栈元素无法向右拓展(新的元素是第一个让他无法拓展的元素)
 * 这样就能求出他能拓展的最大面积了。
 * new.index-stack[top-1].index-1就是宽度*stach[top].height就行了
 * (new.index-stack[top].index) + (stack[top].index-stack[top-1].index)
 * */
typedef struct{
	int index;
	long long height;
}node;
node stack[MAXSIZE];
int top;
node pop()
{
	top--;
	return stack[top+1];
}
void push(node x)
{
	top++;
	stack[top] = x;
	return;
}
void initialise()
{
	node t;
	t.index = 0;
	t.height=-1;
	top=0;
	push(t);
	return;
}
node getTop()
{
	return stack[top];
}
int main()
{
	int N;
	int i,j,k;
	node t,curNode;
	long long ans;
	long long curAns;
	while(scanf("%d",&N),N!=0)
	{
		ans = -1;
		initialise();
		for(i=1;i<=N+1;i++)
		{
			if(i==N+1)
			{
				t.index = N+1;
				t.height=-1;
			}
			else
			{
				scanf("%lld",&t.height);
				t.index=i;
			}
			while(getTop().height > t.height)
			{
				curNode = pop();
			/*	printf("pop the node, Index:%d,Height:%d\n",curNode.index,curNode.height);*/
				curAns = (long long)(t.index - getTop().index -1) * (curNode.height);
				/*printf("i:%d,curAns:%d\n",i,curAns);*/
				if(curAns > ans)
					ans = curAns;
			}
			push(t);
			/*printf("push the node which index is %d height is%d\n",t.index,t.height);*/
			/*
			 * 别忘了把所有元素pop出来。否则会漏掉计算
			 * */
		}
		cout<<ans<<endl;
	}
	return 0;
}



然后是poj1751,,一个最小生成树。。

同上,,后期如果写结题报告会加入传送门。

现在只贴代码。

记录一点,显然是prim,但是关键在于,,把已经修好路的点之间距离设为0

但是!,但是!,还是一样的prim,


绝对不是把那些已经修好的路直接标记成visited,这点很重要。


我们应该做的是,把距离改成0,然后按照prim的流程正常进行求最小生成树。


记得用一个pre数组,在更新low数组的时候,这个数组可以更新跟他连接的最短边的另一个定点


AC代码如下:

#include	<stdio.h>
#include <math.h>
#define INF 300000000
typedef struct{
	int x;
	int y;
}node;
node nodes[751];
double a[751][751];
double low[751];
int vis[751]={0};
int pre[751]={0};

/*-----------------------------------------------------------------------------
 *  计算距离。
 *-----------------------------------------------------------------------------*/
double calcDistance(node *i,node *j)
{
	return (sqrt(  ( (*i).x-(*j).x)*((*i).x-(*j).x)  +  ((*i).y-(*j).y)*((*i).y-(*j).y)  ));

}
int main ( int argc, char *argv[] )
{

	node n;
	int N,M;
	int i,j,k;
	scanf("%d",&N);
	for(i=1;i<=N;i++)
	{
		scanf("%d%d",&n.x,&n.y);
		nodes[i] = n;
	}
	for(i=1;i<=N;i++)
	{
		for(j=1;j<i;j++)
		{
			a[i][j] = calcDistance(&nodes[i],&nodes[j]);
			a[j][i] = a[i][j];
		}
	}
	scanf("%d",&M);
	int x,y;
	for(i=1;i<=M;i++)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=a[y][x] = 0;
	}
	 /*  	for(i=1;i<=N;i++)
		{
		for(j=1;j<=N;j++)
		{
		printf("%lf ",a[i][j]);
		}
		printf("\n");
		}*/


	int pos=0;
	int flag;
	for(i=1;i<=N;i++)
	{
		low[i] = INF;
		pre[i] = 1;
	}
	vis[1] = 1;
	for(i=2;i<=N;i++)
	{
		if(a[1][i] < low[i])
		{
			low[i]=a[1][i];
		}
	}


	double min;
/* 开始定义成了int类型的min.真是作死,,其实,low和a数组都不需要int,,根本不需要开根号 */
	while(1)
	{
/* 		 	for(i=1;i<=N;i++)
			{
			printf("vis[%d]:%d low[%d]:%lf pre[%d]:%d \n",i,vis[i],i,low[i],i,pre[i]);
			}*/


		flag = 1;
		for(i=1;i<=N;i++)
		{
			if(vis[i] == 0)
				flag = 0;
		}
		if(flag)
			break;



		min = INF+1;
		for(i=1;i<=N;i++)
		{
			if(vis[i]==0 && min>low[i])
			{
				min = low[i];
				pos = i;
			}
		}
		vis[pos] = 1;
		if(a[pos][pre[pos]] != 0)
			printf("%d %d\n",pre[pos],pos);
		/* 然后根据pos更新low数组 */

		for(i=1;i<=N;i++)
		{
			if(vis[i]==0 && a[pos][i] < low[i])
			{
				pre[i] = pos;
				low[i] = a[pos][i];
			}
		}

	}

	return 0;
}				/* ----------  end of function main  ---------- */



当然,其实不需要做sqrt,因为不需要真的计算,只需要比较,,这是多余的

因此low和邻接矩阵其实不用开double数组。




今天和别人聊天,所以晚了点,就只写这么些把。。今天的另外一个收获是看懂了quickSort并且自己写了个。


然后看了看qsort的使用方法。

posted @ 2014-07-05 23:41  圣让  阅读(117)  评论(0编辑  收藏  举报