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次,1到N-1这些数都出现了9次。或者i到N这些数出现了8次,1到i-1这些数出现了9次。当N这个服务器坏了,将有8个新服务器出现,替代N,那么如何保持服务器的负载均衡呢?
正确的做法是:对于第一列,从1到N循环放就行,对于第一列,其中每个i在第n*k+i行(0<=k,且n*k+i<=M),所有第一列为i的行应该从N,N-1,一直放到1(遇到i直接跳过就行)。第一列为i+1的行也应该这么放。I从1循环到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;}
- HDU4671
- HDU4671
- hdu4671 构造
- hdu4671 思维构造
- HDU4671 找规律排列问题
- hdu4671异面直线距离
- HDU4671 Backup Plan(构造序列-多校七)
- 默认及非默认端口的动态监听/静态监听实验汇总
- HDU4584
- Python相关的资料
- SharePoint 2013 中使用 delegate control AdditionalPageHead 的注意事项
- 用C/C++调用Java
- HDU4671
- linux epoll模型
- 34-输入5个数字,使用递归的算法倒叙输出
- HDU4690
- 如何使用cygwin编译 ffmpeg
- 如何判断上传的文件类型??是先判断再上传还是先上传再判断?真实的文件类型是什么样的?
- shell脚本和makefile的异同
- HDU 1160(类似于最长上升子序列)
- WebService ----android客户端