Description:
佳佳最近又迷上了某款类似于虚拟人生的网络游戏。在游戏中,佳佳是某旅行团的团长,他需要安排客户住进旅馆。旅馆给了佳佳的旅行团一个房间数的限制。每一个房间有不同的容纳人数和价钱(这个价格是房间的总价格,不是每个人付的)。佳佳决定找到最小的花费,安排参加旅行的人住在这里。但是他遇到了这么一个问题:两个不同性别的人不能住在同一个房间里,除非他们是夫妻;一对夫妻如果在一起住,那么别的人就不能再住进去。你不必让所有的夫妻都单独住在一起。也就是说:
1.给你一些房间,告诉你这些房间的容纳人数和价格
2.安排一定数量的人住到旅馆里,满足:
a.不同性别的人如果不是夫妻那么不能住一起。
b.夫妻如果住在一起,那么房间不能安排其他的人进去。
你来写一个程序帮助佳佳找到安排这些来参加旅行的人住进旅馆所需要的最小花费。
Analysis:
夫妻住在一起有点浪费。。。把夫妻拆开(这还是人吗),让最多只有一对夫妻在一起(qwq),然后DP。
决策时第 i 个房间可以不选,或者住满男的,或者住满女的,要么就住一对夫妻。
另外再考虑有没有夫妻,新开一个数组 g 来进行DP。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[333][333][333],g[333][333][333],a[333],b[333],m,fm,r,c;
int main()
{
scanf("%d%d%d%d",&m,&fm,&r,&c);
for(int i = 1;i <= r;++i)
{
scanf("%d%d",&a[i],&b[i]);
}
for(int i = 0;i <= m;++i)
{
for(int j = 0;j <= fm;++j)
{
f[0][i][j] = g[0][i][j] = 0x7f7f7f7f;
}
}
f[0][0][0] = 0;
for(int i = 1;i <= r;++i)
{
for(int j = 0;j <= m;++j)
for(int k = 0;k <= fm;++k)
{
f[i][j][k] = f[i-1][j][k];
g[i][j][k] = g[i-1][j][k];
if(a[i] >= 2 && j >= 1 && k >= 1) g[i][j][k] = min(g[i][j][k],f[i-1][j-1][k-1] + b[i]);
int tj = max(0,j-a[i]),tk = max(0,k-a[i]);
f[i][j][k] = min(f[i][j][k],f[i-1][tj][k] + b[i]);
g[i][j][k] = min(g[i][j][k],f[i-1][tj][k] + b[i]);
f[i][j][k] = min(f[i][j][k],f[i-1][j][tk] + b[i]);
g[i][j][k] = min(g[i][j][k],g[i-1][j][tk] + b[i]);
}
}
int ans;
if(c == 0) ans = f[r][m][fm];
else ans = min(f[r][m][fm],g[r][m][fm]);
if(ans < 0x7f7f7f7f) printf("%d
",ans);
else printf("Impossible");
return 0;
}