HDU4671

来源:互联网 发布:制作mv软件 编辑:程序博客网 时间:2024/05/29 04:24

HDU4671 备份计划

现在有n个服务器和m个数据库,每个数据库都有一个单子,单子上写的是这n个服务器的一个排列组合,当有人要使用某个数据库时,优先调用这个数据库单子上的第一个服务器来使用,如果这个服务器坏了,就调用第二个,依次类推。这m个数据库的单子要求,n个服务器(可以允许一个服务器坏了,对坏了的服务器不作要求)都负载均衡。当某人通过一个数据库调用了一个服务器时,那么这个服务器就有了一个负载Ai。负载均衡要求:对于任意两个没坏的服务器有

|Ai-AJ|<=1。

输入:包含多个实例,每个位一行N与M(2<=N<=100,1<=M<=100)

以EOF表示输入实例的结束。

输出:对应输出每个实例的M个排列组合。每行一个。

分析:朴素的做法是,依次生成要求的M个排列组合,然后分别判断所有服务器都OK,和某一台服务器坏了(共n中情况),这些情况下,所生成的M个排列组合对应的各服务器负载数据是都满足均衡要求。但是明显生成排列组合时间复杂度太高。

现在对题目的数据进行分析:

1)   若N==M则:要满足所有服务器都OK时要求M个数据库的单子中第一个服务器正好包括了N个服务器(每个一次),不能有哪个服务器多或少一次。且此时也满足任一服务器坏了的条件。

如N=5,M=5时为:

 

1…

2…

3…

4…

5…

2)   若N>M则:所有服务器OK时,要求M个数据库的单子中第一个服务器正好包括了M个不同的服务器(每个一次)。M个单子的第二列只能包括剩下的N-M个服务器中的任意一个或几个。依然满足任一服务器坏了的情况。

N=8且M=5时;

1 6 …

2 7…

3 8…

4 6…

5 6…

3)   若N<M时则:M个排列的第一列要求N各数循环填写就行,这样的结果就是N个服务器中,集合S1中的服务器在M个排列中出现了(M)/N次,集合S2中的服务器在M个排列中出现了(M-1)/N+1次。服务器全OK时不用考虑第二列,但是现在考虑这种情况:

假设N这个数出现了8次,1N-1这些数都出现了9次。或者iN这些数出现了8次,1i-1这些数出现了9次。当N这个服务器坏了,将有8个新服务器出现,替代N,那么如何保持服务器的负载均衡呢?

正确的做法是:对于第一列,从1N循环放就行,对于第一列,其中每个i在第n*k+i行(0<=k,且n*k+i<=M),所有第一列为i的行应该从NN-1,一直放到1(遇到i直接跳过就行)。第一列为i+1的行也应该这么放。I1循环到N即可。

N=3,M=14时:

1 3 2

2 3 1

3 2 1

1 2 3

2 1 3

3 1 2

1 3 2

2 3 1

3 2 1

1 2 3

2 1 3

3 1 2

1 3 2

2 3 1

#include<cstdio>#include<cstring>using namespace std;int p[200][200];int use[200];int main(){    int n,m;    while(scanf("%d%d",&n,&m)==2)    {        if(n==m)        {            for(int i=1;i<=m;i++)                p[i][1]=i;            for(int i=1;i<=m;i++)            {                memset(use,0,sizeof(use));                use[p[i][1]]=1;                for(int j=2;j<=n;j++)                {                    for(int k=1;k<=n;k++)if(use[k]==0)                    {                        use[k]=1;                        p[i][j]=k;                        break;                    }                }            }        }        else if(n>m)        {            for(int i=1;i<=m;i++)                p[i][1]=i;            for(int i=1;i<=m;i++)                p[i][2]=n;            for(int i=1;i<=m;i++)            {                memset(use,0,sizeof(use));                use[p[i][1]]=use[p[i][2]]=1;                for(int j=3;j<=n;j++)                {                    for(int k=1;k<=n;k++)if(use[k]==0)                    {                        use[k]=1;                        p[i][j]=k;                        break;                    }                }            }        }        else if(n<m)        {            for(int i=1;i<=m;i++)                p[i][1]=(i-1)%n+1;//赋值第一列,并记录次数            for(int i=1;i<=n;i++)            {                int start=n;                if(i==n)start--;                for(int k=0;k*n+i<=m;k++)                {                    p[k*n+i][2]=start--;                    if(start==0)start=n;                    if(start==i)start--;                    if(start==0)start=n;                }            }            for(int i=1;i<=m;i++)            {                memset(use,0,sizeof(use));                use[p[i][1]]=use[p[i][2]]=1;                for(int j=3;j<=n;j++)                {                    for(int k=1;k<=n;k++)if(use[k]==0)                    {                        use[k]=1;                        p[i][j]=k;                        break;                    }                }            }        }        for(int i=1;i<=m;i++)        {            for(int j=1;j<=n;j++)                printf("%d ",p[i][j]);            printf("\n");        }    }    return 0;}


0 0