比赛 20120706 评测结果 WWWWWWWWWA
题目名称 排队 最终得分 10
用户昵称 Citron酱 运行时间 0.000 s
代码语言 C++ 内存使用 0.00 MiB
提交时间 2012-07-06 11:22:53
显示代码纯文本
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cmath>

#define I_F "queuea.in"
#define O_F "queuea.out"

const int MAXn=1000;
const int P1=1000;
const int P2=5;

struct edge
{
	int x;
	edge *next;
};

int n, m;
short k;
int h[MAXn];
int fam[MAXn][MAXn];
edge *map[MAXn]={NULL};
int d[MAXn]={0}, c[MAXn];
int g[MAXn][MAXn];
int l[MAXn]={0};
long min1[MAXn];
long min2[MAXn][MAXn];
long ans;

void Input();
void Getmap();
void Topdev();
template<typename Any>
inline void Swap(Any&, Any&);
template<typename Any>
void Arrcpy(const Any*, Any*, const int&, const int=-1, const int=-1);
template<typename Any>
inline Any Min(const Any&, const Any&);
long Rand1(int*, const int&);
long Rand2(int*, const int&, const long);
void Search();
void Output();

int main()
{
	Input();
	Getmap();
	Topdev();
	Search();
	Output();
	return 0;
}

void Input()
{
	freopen(I_F,"r",stdin);
	scanf("%d%hd",&n,&k);
	for (int i=0; i<n; ++i)
		scanf("%d",&h[i]);
	for (int i=0; i<n; ++i)
		for (int j=0; j<n; ++j)
			scanf("%d",&fam[i][j]);
}

void Getmap()
{
	edge *temp;
	for (int i=0; i<n; ++i)
		for (int j=i+1; j<n; ++j)
			if (h[j]-h[i]>=k)
			{
				++d[j];
				temp=map[i];
				map[i]=new edge;
				map[i]->x=j;
				map[i]->next=temp;
			}
}

void Topdev()
{
	m=n;
	bool flag=true;
	edge *temp;
	for (int i=0; i<n && flag; ++i)
	{
		flag=false;
		for (int j=0; j<n; ++j)
			if (d[j]==0)
				g[i][l[i]++]=j,
				flag=true;
		for (int j=0; j<l[i]; ++j)
		{
			d[g[i][j]]=-1;
			c[g[i][j]]=i;
			while (map[g[i][j]]!=NULL)
			{
				--d[map[g[i][j]]->x];
				temp=map[g[i][j]];
				map[g[i][j]]=map[g[i][j]]->next;
				delete temp;
			}
		}
		if (!flag)
			m=i;
	}
}

template<typename Any>
inline void Swap(Any &a, Any &b)
{
	Any t=a;
	a=b;
	b=t;
}

template<typename Any>
void Arrcpy(const Any *a, Any *b, const int &l, const int ri=-1, const int le=-1)
{
	for (int i=0; i<l; ++i)
		b[i]=a[i];
	if (le>=0)
		Swap(b[le],b[0]);
	if (ri>=0)
		Swap(b[ri],b[l-1]);
}

template<typename Any>
inline Any Min(const Any &a, const Any &b)
{
	return (a<b)?a:b;
}

long Rand1(int *s, const int &l)
{
	if (l>3)
	{
		int a, b;
		for (int i=0; i<2*sqrt(l); ++i)
		{
			a=1+rand()%(l-2);
			b=1+rand()%(l-2);
			Swap(s[a],s[b]);
		}
	}
	long t=0;
	for (int i=1; i<l; ++i)
		t+=fam[s[i-1]][s[i]];
	return t;
}

long Rand2(int *s, const int &l, const long x)
{
	if (l>3)
	{
		int a, b;
		a=1+rand()%(l-2);
		for (b=1+rand()%(l-2); b==a; b=1+rand()%(l-2));
		if (b<a)
			Swap(a,b);
		long t=x;
		if (a>0)
			t=t-fam[s[a-1]][s[a]]+fam[s[a-1]][s[b]];
		if (b<l-1)
			t=t-fam[s[b+1]][s[b]]+fam[s[b+1]][s[a]];
		if (t<x)
			for (int i=a; i<a+(b-a+1)/2; ++i)
				Swap(s[i],s[b+a-i]);
		else if (rand()%P1<P2)
			for (int i=a; i<a+(b-a+1)/2; ++i)
				Swap(s[i],s[b+a-i]);
		else
			return x;
		return t;
	}
	else
		return x; 
}

void Search()
{
	long now;
	int w[MAXn];
	long t[MAXn];
	for (int i=0; i<l[0]; ++i)
		if (h[g[0][i]]<h[g[0][0]])
			Swap(g[0][i],g[0][0]);
	if (l[0]>1)
	{
		for (int i=1; i<l[0]; ++i)
		{
			min1[i]=LONG_MAX;
			Arrcpy(g[0],w,l[0],i);
			for (int p=0; p<2*log2(l[0]); ++p)
			{
				now=Rand1(w,l[0]);
				for (int q=0; q<2*sqrt(l[0]); ++q)
				{
					now=Rand2(w,l[0],now);
					min1[i]=Min(min1[i],now);
				}
			}
		}
		min1[0]=-1;
	}
	else
		min1[0]=0;
	
	for (int i=1; i<m; ++i)
	{
		if (l[i]>1)
		{
			for (int j=0; j<l[i]; ++j)
				for (int k=0; k<l[i]; ++k)
					if (j!=k)
					{
						Arrcpy(g[i],w,l[i],k,j);
						for (int p=0; p<2*log2(l[i]); ++p)
						{
							now=Rand1(w,l[i]);
							for (int q=0; q<2*sqrt(l[i]); ++q)
							{
								now=Rand2(w,l[i],now);
								min2[j][k]=Min(min2[j][k],now);
							}
						}
					}
		}
		else
			min2[0][0]=0;
		for (int j=0; j<l[i]; ++j)
		{
			t[j]=LONG_MAX;
			for (int k=0; k<l[i-1]; ++k)
				for (int o=0; o<l[i]; ++o)
					if (min1[k]>=0 && min2[o][j]>=0)
						t[j]=Min(t[j],min1[k]+min2[o][j]+fam[g[i-1][k]][g[i][o]]);
			Arrcpy(t,min1,l[i]);
		}
	}
	
	ans=LONG_MAX;
	for (int i=0; i<l[m-1]; ++i)
		ans=Min(ans,min1[i]);
}

void Output()
{
	freopen(O_F,"w",stdout);
	printf("%ld\n",ans);
}