UVA_10817

    本来一开始没头绪的,后来寝室一哥们问我背包问题是什么,我解释完了之后突然发现这个问题也可以用背包去做。

    由于对于每一个应聘的老师要么要要么不要,这就是0-1背包的特点了,剩下的问题是我们是否可以找到一个相当于体积的状态呢。

    实际我们可以把每个课程还需几个老师教这一状态看做0-1背包问题的体积,不妨设f[i][j]为取到第i个老师课程状态为j时的最小花费,那么f[i][j]=min{f[i-1][j],f[i-1][k]+w[i]},其中k状态是由j状态加上第i个老师可以教课的状态得到的,如果某项大于2,就当做2来看待,意思是这个老师可以不教这门课。

    初始化边界的时候将f[0][j]初始化成必须雇佣的老师所花费的总金钱即可,其中状态j各项课程状态的值都要不小于所有雇佣的老师的和状态。举个例子,比如一共3门课,而所有必要老师的和状态是2 1 1,也就是说还有两门课各缺一个老师,一门课缺两个老师,那么我们把2 1 1、2 2 1、2 1 2、2 2 2均初始化成起始费用,意思是必须雇佣的老师里面某些老师也可以不教某些课程,而让新雇佣的老师去教。

    当然,在计算的时候还要把各项课程状态压缩成一个整数去计算。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define MAXD 10000
#define MAXN 110
#define INF 1000000000
int S, M, N, P, f[MAXN][MAXD], w[MAXD], t[MAXD][10], a[10], p[10];
char b[100];
int init()
{
int i, j, k;
gets(b);
sscanf(b, "%d%d%d", &S, &M, &N);
if(!S)
return 0;
return 1;
}
void solve()
{
int i, j, k, v, res, temp, ok;
v = 0;
for(i = 1; i <= S; i ++)
a[i] = 2;
for(i = 0; i < M; i ++)
{
gets(b);
k = strlen(b);
sscanf(b, "%d", &temp);
v += temp;
for(j = 0; isdigit(b[j]); j ++);
for(++ j; j < k; j ++)
{
sscanf(&b[j], "%d", &temp);
if(a[temp])
a[temp] --;
while(isdigit(b[j]))
j ++;
}
}
memset(t, 0, sizeof(t));
for(i = 1; i <= N; i ++)
{
gets(b);
k = strlen(b);
sscanf(b, "%d", &temp);
w[i] = temp;
for(j = 0; isdigit(b[j]); j ++);
for(++ j; j < k; j ++)
{
sscanf(&b[j], "%d", &temp);
t[i][temp] = 1;
while(isdigit(b[j]))
j ++;
}
}
memset(f, 0x3f, sizeof(f));
for(i = 1, P = 0; i <= S; i ++)
P = 3 * P + 2;
for(i = 0; i <= P; i ++)
{
temp = i;
for(j = 1; j <= S; j ++)
{
p[j] = temp % 3;
temp /= 3;
}
ok = 1;
for(j = 1; j <= S && p[j] >= a[j]; j ++);
if(j == S + 1)
f[0][i] = v;
}
for(i = 1; i <= N; i ++)
for(j = 0; j <= P; j ++)
{
f[i][j] = f[i - 1][j];
temp = j;
for(k = 1; k <= S; k ++)
{
p[k] = temp % 3;
temp /= 3;
}
for(k = 1; k <= S; k ++)
if(t[i][k] && p[k] < 2)
p[k] ++;
temp = 0;
for(k = S; k >= 1; k --)
temp = 3 * temp + p[k];
if(f[i - 1][temp] + w[i] < f[i][j])
f[i][j] = f[i - 1][temp] + w[i];
}
printf("%d\n", f[N][0]);
}
int main()
{
while(init())
solve();
return 0;
}


posted on 2011-12-07 09:04  Staginner  阅读(1026)  评论(2编辑  收藏  举报