HDU4671 找规律排列问题

Source: 2013 Multi-University Training Contest 7 1006

题目大意: 题目意思还是比较麻烦的,当时做多校的时候询问题意的人就特别多。给你n个服务器,m个数据库。每个数据库有一个序列,每个序列有n个数,作为优先请求的顺寻,例如n=5,m=3.对于 第一个数据库假设排列是 1 2 3 4 5那么如果1号服务器没坏,这个数据库就向一号服务器递交申请使用,这时候2号是空闲的。如果一坏了,那么将使用二号,以此类推。那么m个数据库就会有m个n个数的排列。但是这样的排列必须满足一定得条件,就是对于一个时刻,最多被使用服务器的次数减去最少被使用的服务器次数不能超过1(<=1)。这就是说平衡每个服务器的使用,尽可能使得工作平均。同时如果假定一个服务器坏掉(最多一个),这是的工作状态也是满足这个平衡条件的(坏掉的不计入使用次数)。输出这样的排列,Special Judge,输出一种可能即可。

给的样例 n=5 m=3

2 4 3 1 5        如果都没坏, 1,2,3使用1次,4,5使用0,最大不超过1. 如果4,5坏掉,对使用暂时没用影响。如果1坏了,那么2,5,3被使用……2,3坏掉一样
1 5 4 2 3
3 5 2 4 1

思路:因为要尽可能使每种服务器使用均衡,对于第一次序的,只需要按照1,2,3……n,1,2,3……这样排列就好了。

例如 n=6 m=3     为    n=3 m=6 为  

1                                    1

2                                    2

3                                    3

                                      1

                                      2

                                      3

因为最多坏掉一个,其实只是将第二列左移到坏掉的一列上,其实只需要考虑前两列。因为我们的排序时尽可能使小的号码使用先,所以号码大的必然比小的使用次数少。那么我们对于替换就优先使用大序号替换。 我们再开一个数组t,记录当前替换序号,初始化为n,我们只需要讨论一号工作站相同的情况的第二列,设为a。 如果第二列与第一列不同 t[a]加入第二列,t[a]--;如果与第一列相同,t[a]-1加入再--。之后两列拍好,后面n-2列只要不重复即可。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[102];
int a[102][3];
int main()
{
    int n,m;  //n为sever m 为database
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(s,0,sizeof(s));
        memset(a,0,sizeof(a));
        int temp=0;
        for(int i=1; i<=m; i++)
        {
            a[i][1]=(temp)%n+1;
            temp=(temp)%n+1;
        }
        temp=n;
        for(int i=1; i<=n; i++)
            s[i]=n;

        for(int i=1; i<=m; i++)
        {
            int t=a[i][1];
            if(a[i][1]!=s[t])
            {
                a[i][2]=(s[t]);
                s[t]=(s[t]-2+n)%n+1;
            }
            else
            {
                a[i][2]=(s[t]-2+n)%n+1;
                s[t]=(s[t]-2+n)%n+1;
                s[t]=(s[t]-2+n)%n+1;
            }
        }
        int temp1=1;
        for(int i=1; i<=m; i++)
        {
            temp1=1;
            for(int j=1; j<=n; j++)
            {
                if(j==1||j==2) cout<<a[i][j]<<" ";
                else
                {
                    while(temp1==a[i][1]||temp1==a[i][2])
                        temp1++;
                    cout<<temp1;
                    if(j!=n)cout<<" ";
                    temp1++;
                }
            }
            cout<<endl;
        }
    }
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值