Headmaster's Headache UVA

UVA-10817

ans[i][s1][s2]表示考虑前i个人时,有至少1人教的科目集合为s1,有至少2人教的科目集合为s2时的最少工资
集合用一个数字表示,转换成二进制后从后面开始数第i位的状态(1/0)表示第i个科目的状态(满足/不满足某条件)
st[i]表示第i个人能教的课程集合,cost[i]表示第i个人的工资
ans[i][s1'][s2']=min(ans[i-1][s1'][s2'],ans[i-1][s1][s2]+cost[i])
s1'=s1|st[i]
s2'=s2|(s1&st[i])
压缩掉一维:
显然,s1'>=s1,s2'>=s2
因此,ans[s1'][s2']=min(ans[s1'][s2'],ans[s1][s2]+cost[i]) s1和s2从大到小

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 char tt[500];
 6 int s,m,n,ans1,sa,sb;
 7 int ans[1<<8][1<<8];
 8 int st[110],cost[110];
 9 int main()
10 {
11     int i,t,point,maxj,j,j1;
12     scanf("%d%d%d",&s,&m,&n);
13     while(s!=0)
14     {
15         memset(ans,0x3f,sizeof(ans));
16         memset(st,0,sizeof(st));
17         cin.getline(tt,500);
18         ans1=0;
19         sa=0;sb=0;
20         for(i=1;i<=m;i++)
21         {
22             //memset(tt,'',sizeof(tt));
23             cin.getline(tt,500);
24             point=0;
25             sscanf(tt,"%d",&t);
26             ans1+=t;
27             while(tt[point]<='9'&&tt[point]>='0')    ++point;
28             while(tt[point]==' ')    ++point;
29             while(point<strlen(tt))
30             {
31                 sscanf(tt+point,"%d",&t);
32                 t=1<<(t-1);
33                 sb|=sa&t;
34                 sa|=t;
35                 while(tt[point]<='9'&&tt[point]>='0')    ++point;
36                 while(tt[point]==' ')    ++point;
37             }
38         }
39         ans[sa][sb]=ans1;
40         for(i=1;i<=n;i++)
41         {
42             //memset(tt,'',sizeof(tt));
43             cin.getline(tt,500);
44             point=0;
45             sscanf(tt,"%d",&cost[i]);
46             while(tt[point]<='9'&&tt[point]>='0')    ++point;
47             while(tt[point]==' ')    ++point;
48             while(point<strlen(tt))
49             {
50                 sscanf(tt+point,"%d",&t);
51                 st[i]|=1<<(t-1);
52                 while(tt[point]<='9'&&tt[point]>='0')    ++point;
53                 while(tt[point]==' ')    ++point;
54             }
55         }
56         maxj=(1<<s)-1;
57         for(i=1;i<=n;i++)
58             for(j=maxj;j>=0;j--)
59                 for(j1=maxj;j1>=0;j1--)
60                 {
61                     sa=j|st[i];
62                     sb=j1|(j&st[i]);
63                     ans[sa][sb]=min(ans[sa][sb],ans[j][j1]+cost[i]);
64                 }
65         printf("%d
",ans[maxj][maxj]);
66         scanf("%d%d%d",&s,&m,&n);
67     }
68     return 0;
69 }
原文地址:https://www.cnblogs.com/hehe54321/p/7340186.html