现在的位置: 首页 > 综合 > 正文

HDU 4671 Backup Plan (水题)

2018年02月23日 ⁄ 综合 ⁄ 共 1271字 ⁄ 字号 评论关闭

题意:(已经过本人转化。。。)有M个数据站,N个服务器,每个数据站有一个序列,这个序列就是该数据站存放自己的数据备份时的优先级顺序,如果排在第一的服务器坏了,就往排第二的服务器里存放自己的备份,以此类推直到可以存放自己的备份为止。这么一来,每个服务器就会存放一定数量的数据站的数据备份。

例如,所有服务器都没坏,而A数据站和B数据站拥有的服务器优先级序列中第一个都是服务器2,那么第二个服务器就存放了两个备份了,因为存放了A数据站的和B数据站的数据。

现在记录每个服务器所存放的备份数量为A[i],要求任意i,和j满足|A[i]-A[j]|<=1。

但是,每个服务器都会有坏掉的可能,要求任意坏掉恰好一个服务器的时候都有任意i,和j满足|A[i]-A[j]|<=1。要你输出所有数据站的优先级序列,使得上述条件成立。

思路:在服务器都没坏的时候,注意到服务器每排在一个数据站的第一位时,这个服务器存放的备份就多一次,也就是说,一个服务器排在K个数据站的第一位的话,A[i]=K。题目可以转化成有M颗糖果,N个盒子,每个盒子装A[i]颗糖果。要求|A[i]-A[j]|<=1,这个很好办,只要糖果均匀分派就行了。

例如10个糖果,3个盒子,那么只要分配成4,3,3就可以了。

那么,如果一个服务器坏了,那么它排第一位的时候都变成了排在第二位的那个来代替。相当于把其中一盒糖果回收,把那个盒撤掉,再重新均匀分配回收的糖果。例如4,3,3,现在把第2盒糖果回收,重新分配,那么就会分配成5,5。

知道思路以后,只要均等分配排第一的次数,然后对于每个排第一的数字,又均匀分配剩下的数字就好了。确定了排头的两个,后面就可以任意排列了,因为每次只会坏掉一个服务器,所以只有前两个服务器有效。

#include<cstdio>
#include<cstring>

int N,M;
int f2[105][2];//记录每个数据站的排头两个服务器
int A[105];

int main()
{
	while(~scanf("%d %d",&N,&M))
	{
		memset(A,0,sizeof(A));
		memset(f2,0,sizeof(f2));
		
		for(int i=1;i<=N;++i)//处理A[i]
		{
			A[i]=M/N;//体现均匀分配
			if(M%N>=i) ++A[i];//将余下的再均匀分配
		}
		
		int cnt=1;
		for(int i=1;i<=N;++i)
			for(int j=1,k=N;j<=A[i];++j,--k) 
			{
				while(i==k || k==0)
				{
				if(i==k) --k;
				if(k==0) k=N;
				}
				f2[cnt][0]=i,f2[cnt][1]=k,++cnt;//分配每个数据站的排头两个服务器
			}

		for(int i=1;i<=M;++i)//输出
		{
			printf("%d %d",f2[i][0],f2[i][1]);
			for(int j=1;j<=N;++j) if(j!=f2[i][0] && j!=f2[i][1]) printf(" %d",j);
			printf("\n");
		}
	}
	return 0;
}

抱歉!评论已关闭.