“医院/居民问题”确实可行,但这取决于您的限制条件:
- 医院有最大容量,并将按照需求程度来排序居民。
- 居民将排序医院。
- 没有其他可能的约束条件。
在您的情况下,医院是工人,而居民是插槽。
- 插槽可以订购工人(也许您更喜欢在早上有经验的工人...)。
- 工人可以订购插槽。
- 但是您不能有其他约束条件,例如:“我早上已经工作了,我不想在同一天晚上再次工作”。
如果这对您来说没问题,那么您有两种可能性:
- 您想优先考虑工人:“以医院为导向的情况”。
您将尝试将工人分配到他们首选的插槽。
- 您想优先考虑插槽:“以居民为导向的情况”。
每个插槽都有他们首选的工人。
我去年不得不编写它,以下是代码。
const int MAX_R = 1000;
const int MAX_H = 1000;
const int INF = 1000*1000*1000;
您需要填写输入变量。
- R_pref和H_pref是居民/医院的偏好列表
- H_rank[h][r]是r在H_pref[h]中的排名:即h的偏好列表中r的位置
就是这样。
int R, H;
int C[MAX_H];
vector<int> R_pref[MAX_R], H_pref[MAX_H];
int H_rank[MAX_H][MAX_R];
int R_rank[MAX_R][MAX_H];
无需在下面进行操作。
int RankWorst[MAX_H];
int BestH[MAX_R];
int BestR[MAX_H];
int Size[MAX_H];
int M[MAX_R];
void stable_hospitals_RO()
{
for(int h = 0 ; h < H ; h++)
RankWorst[h] = H_pref[h].size()-1;
fill_n(BestH, R, 0);
fill_n(Size, H,0);
fill_n(M,R,INF);
for (int i = 0; i < R; i++)
for (int r = i; r >= 0;)
{
if(BestH[r] == int(R_pref[r].size()))
break;
const int h = R_pref[r][BestH[r]++];
if(Size[h]++ < C[h])
{
M[r] = h;
break;
}
int WorstR = H_pref[h][RankWorst[h]];
while(WorstR == INF || M[WorstR] != h)
WorstR = H_pref[h][--RankWorst[h]];
if(H_rank[h][r] < RankWorst[h])
{
M[r] = h;
M[r = WorstR] = INF;
}
}
}
void stable_hospitals_HO()
{
fill_n(BestR, H, 0);
fill_n(Size, H,0);
fill_n(M,R,INF);
vector<int> SH;
for (int h = 0; h < H; h++)
SH.push_back(h);
while(!SH.empty())
{
int h = SH.back();
if(Size[h] == C[h] || BestR[h] == int(H_pref[h].size()))
{
SH.pop_back();
break;
}
const int r = H_pref[h][BestR[h]++];
if(M[r] == INF || R_rank[r][h] < R_rank[r][M[r]])
{
if(++Size[h] == C[h])
SH.pop_back();
if(M[r] != INF)
{
Size[M[r]]--;
SH.push_back(M[r]);
}
M[r] = h;
}
}
}
以下是一个示例,展示如何通过偏好列表来构建排名。(在该示例中,偏好列表存在于标准输入中。)
int main()
{
scanf("%d%d",&R,&H);
int num;
for(int r = 0 ; r < R ; r++)
{
scanf("%d",&num);
R_pref[r].resize(num);
for(int h = 0 ; h < num ; h++)
{
scanf("%d",&R_pref[r][h]);
R_rank[r][R_pref[r][h]] = h;
}
}
for(int h = 0 ; h < H ; h++)
{
scanf("%d",&C[h]);
scanf("%d",&num);
H_pref[h].resize(num);
for(int r = 0 ; r < num ; r++)
{
scanf("%d",&H_pref[h][r]);
H_rank[h][H_pref[h][r]] = r;
}
}
stable_hospitals_RO();
printf("\n\n\n\n");
stable_hospitals_HO();
return 0;
}
举个例子:
医院1到3,6名居民。
H_pref:
- 1 -> 2 5 6 1(偏爱2然后是5、6、1)
- 2 -> 4 2 1 6 3 5
- 3 -> 1 2
R_pref:
- 1 -> 1 2 3
- 2 -> 3 1
- 3 -> 2 1
- 4 -> 1 3 2
- 5 -> 3 2 1
- 6 -> 3
H_rank:
- 1 -> 4 1 INF INF 2 3(1在H_pref[1]中排名第4位,3不在其中)
- 2 -> 3 2 5 1 6 4
- 3 -> 1 2 INF INF INF INF
R_rank同理。
医院不必为每个人排名,也可以比其容量更少的人排名。