您的位置:首页 > 其它

UVa 10817 Headmaster's Headache(状态压缩DP)

2012-11-26 11:38 302 查看
题意:

有一个学校想要聘请老师,要求每个学科都有两个以上的老师授课,并且要使总费用最小。有S(最多8个)个学科,现任的M(最多20个)个老师(你必须继续聘请他们),N(最多100个)份申请。后来的M行每行有至少两个整数,表示现任的老师的工资,和他所教授的课程(可能不止一个)。再后来的N行每行有也有至少两个整数表示聘请这个老师所需的费用,以及他所教授的课程(可能不止一个)。

思路:

/article/4928162.html

如何进行状态压缩很关键,链接中的思路有待于细细琢磨。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cctype>
#include <algorithm>
using namespace std;

const int MAXD = 10000;
const int MAXN = 110;
int s, m, n;
int dp[MAXN][MAXD];
int need[12], tech[MAXN][12], state[12];
int cost[MAXN];

void solve()
{
for (int i = 1; i <= s; ++i)
need[i] = 2;

char b[100];
int v = 0;
for (int i = 0; i < m; ++i)
{
gets(b);
int k = strlen(b);
int t;
sscanf(b, "%d", &t);
v += t;

int j = 0;
while (isdigit(b[j]))
++j;

for (++j; j < k; ++j)
{
sscanf(&b[j], "%d", &t);
if (need[t])
--need[t];

while (isdigit(b[j]))
++j;
}
}

memset(tech, 0, sizeof(tech));
for (int i = 1; i <= n; ++i)
{
gets(b);
int k = strlen(b);
int t;
sscanf(b, "%d", &t);
cost[i] = t;

int j = 0;
while (isdigit(b[j]))
++j;

for (++j; j < k; ++j)
{
sscanf(&b[j], "%d", &t);
tech[i][t] = 1;

while (isdigit(b[j]))
++j;
}
}

memset(dp, 0x3f, sizeof(dp));
int P = 0;
for (int i = 1; i <= s; ++i)
P = 3 * P + 2;

for (int i = 0; i <= P; ++i)
{
int t = i;
for (int j = 1; j <= s; ++j)
state[j] = t % 3, t /= 3;
int j;
for (j = 1; j <= s && state[j] >= need[j]; ++j);
if (j == s + 1)
dp[0][i] = v;
}

for (int i = 1; i <= n; ++i)
{
for (int j = 0; j <= P; ++j)
{
int t = j;
for (int k = 1; k <= s; ++k)
state[k] = t % 3, t /= 3;

for (int k = 1; k <= s; ++k)
if (tech[i][k] && state[k] < 2)
++state[k];

t = 0;
for (int k = s; k >= 1; --k)
t = 3 * t + state[k];

dp[i][j] = min(dp[i-1][j], dp[i-1][t] + cost[i]);
}
}
}

int main()
{
char b[100];
while (gets(b))
{
sscanf(b, "%d %d %d", &s, &m, &n);
if (!s)
break;

solve();
printf("%d\n", dp
[0]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: