zoukankan      html  css  js  c++  java
  • UVA

    题目大意:有一些老师,每一位都有自己的工资以及教授的课程。共s<=8个课程。其中的一些老师必须选择,问你保证每节课至少有一个老师的最少总工资。

    题解:

    首先很容易想到状态压缩,搞一个3进制的数,分别表示每一门课程的情况,一共38=6561。但是这样是不行的,相当于暴力啊!
    一个套路:三进制转化为二进制*2。也就是搞一个216的数,1~8和9~16表示每门课程,这样就可以利用位运算了。
    然后知道这个就很显然的,一个背包问题。要注意,这样转化为二进制之后,要定义一条规则,每次添加课程,优先1~8位,有了就再加到9~16位即可。
    处理出所有强制选择的老师的授课状态S,令dp[S]=sum{c[]}。其他的全是INF。然后从All=(1<<(s*2)-1到S。当成01背包做即可。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define RG register
     8 #define LL long long
     9 #define fre(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout);
    10 using namespace std;
    11 const int MAXN=1000;
    12 int s,n,m,S,sum,All;
    13 int c[MAXN],a[MAXN],dp[1<<16];
    14 char ch;
    15 int main()
    16 {
    17    while(scanf("%d%d%d",&s,&n,&m)!=EOF)
    18       {
    19          if(s==0)break;
    20          All=(1<<(s*2))-1;
    21          for(int i=1,flag,x;i<=n+m;i++)//鬼里鬼气的输入
    22             {
    23                a[i]=0;
    24                scanf("%d",&c[i]);
    25                flag=0;
    26                while(1)
    27                   {
    28                      ch=getchar();
    29                      while(ch<'0'||ch>'9')
    30                         {
    31                            if(ch=='
    '||ch=='
    ') { flag=1; break; }
    32                            ch=getchar();
    33                         }
    34                      if(flag)break;
    35                      x=0;
    36                      while('0'<=ch&&ch<='9')x=x*10+(ch-'0'),ch=getchar();
    37                      a[i]|=(1<<(x-1));
    38                      if(ch=='
    '||ch=='
    ')break;
    39                   }
    40             }
    41          S=sum=0;
    42          for(int i=1;i<=n;i++)//按照规则,优先填后面的
    43             {
    44                sum+=c[i];
    45                int p=S&a[i];
    46                S|=(p<<s);
    47                S|=a[i];
    48             }
    49          memset(dp,0x3f3f3f3f,sizeof dp);
    50          dp[S]=sum;
    51          for(int i=n+1;i<=n+m;i++)
    52             {
    53                for(int j=All;j>=S;j--)//按照规则,优先填后面的
    54                   {
    55                      int p=a[i]&j;
    56                      p=a[i]|(p<<s);
    57                      dp[j|p]=min(dp[j|p],dp[j]+c[i]);
    58                   }
    59             }
    60          printf("%d
    ",dp[All]);
    61       }
    62    return 0;
    63 }
  • 相关阅读:
    poj3669 广搜
    检索所有课程都选修的的学生的学号与姓名
    UVA10160 Servicing Stations
    uva11205 The broken pedometer 子集生成
    poj1101 the game 广搜
    poj3009 Curling 2.0 深搜
    poj 1564 Sum It Up 搜索
    HDU 2268 How To Use The Car (数学题)
    codeforces 467C George and Job(简单dp,看了题解抄一遍)
    HDU 2267 How Many People Can Survive(广搜,简单)
  • 原文地址:https://www.cnblogs.com/D-O-Time/p/7717803.html
Copyright © 2011-2022 走看看