UVA10817 Headmaster's Headache

链接:UVA10817

题意:需要讲s个课程,现在有m个老师和n个应聘的,要求没门课最少有两名老师,求出最少支付的工资。

状压DP。。。。。用一个三维数组d[i][s1][s2],i表示第i个老师(or应聘者),s1表示恰好有一个人教的科目的集合,s2表示至少有两个教科目的集合,i表示考虑前i个人的情况。。

然后记忆化搜索,当搜到i为n+m时,如果s2还不是(1<

转移方程是,d(i,s1,s2)=min(d(i+1,s1',s2')+c[i],d(i+1,s1,s2));...。第一种状态表示聘用i,第二种表示不用,第二种只有当i>=m时才有。

位运算:&表示寻找一个元素是否在这个集合,|表示加进这个集合,^表示去掉。

#include
#include
#include
using namespace std;
const int MAXN=125;
const int INF=1<<30;
int m,n,s,st[MAXN],d[MAXN][1<<8][1<<8],c[MAXN];
int dp(int i,int s0,int s1,int s2)
{
    if(i==m+n)
        return s2==(1<=0)
        return ans;
    ans=INF;
    if(i>=m)
        ans=min(ans,dp(i+1,s0,s1,s2));
    int m0=st[i]&s0,m1=st[i]&s1;
    s0^=m0,s1=(s1^m1)|m0,s2|=m1;
    ans=min(ans,c[i]+dp(i+1,s0,s1,s2));
    return ans;
}
int main()
{
    int i;
    while(scanf("%d%d%d",&s,&m,&n)!=EOF&&s)
    {
        int x;
        memset(d,-1,sizeof(d));
        memset(st,0,sizeof(st));
        for(i=0;i


你可能感兴趣的:(状态压缩DP,DP)