zoukankan      html  css  js  c++  java
  • UVA 10817 Headmaster's Headache

    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;
    }


  • 相关阅读:
    暑假集训Day14 I (莫队)
    暑假集训Day14 G (gcd 数学)
    暑假集训Day13 H (进制转换 数学)
    暑假集训Day13 C (二分+贪心)
    暑假集训Day13 I (区间DP)
    暑假集训Day12 H (数论 STL)
    Java8中list转map方法总结
    Typora ---一款简洁的Markdown编辑器
    java8 map flatmap
    Elasticsearch基本查询总结
  • 原文地址:https://www.cnblogs.com/staginner/p/2278727.html
Copyright © 2011-2022 走看看