其实就是个记忆化搜索+位运算
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int inf=1<<29;
const int maxn=120;
const int maxm=1<<8;
struct Node
{
int cost;
int tec;
}t[maxn];
int s,m,n,dp[maxn][maxm][maxm];
char str[1010];
void Init()
{
memset(dp,-1,sizeof(dp));
memset(t,0,sizeof(t));
}
int DFS(int index,int s0,int s1,int s2)
{
if(s2==(1<<s)-1)
return 0;
if(dp[index][s1][s2]>=0)
return dp[index][s1][s2];
if(index==n+m)
return inf;
int ss1=s1,ss2=s2;
int ans=DFS(index+1,s0,s1,s2);
int m0=t[index].tec&s0;
int m1=t[index].tec&s1;
s0^=m0;s1=(s1^m1)|m0;s2|=m1;
ans=min(ans,t[index].cost+DFS(index+1,s0,s1,s2));
return dp[index][ss1][ss2]=ans;
}
int main()
{
while(scanf("%d%d%d",&s,&m,&n)&&s)
{
Init();
getchar();
for(int i=0;i<n+m;i++)
{
gets(str);
int len=strlen(str),num=0;
bool first=true;
for(int j=0;j<len;j++)
{
if(str[j]==' ')
{
if(first)
{
t[i].cost=num;
first=false;
}
else
t[i].tec|=(1<<(num-1));
num=0;
}
else
num=num*10+str[j]-'0';
}
t[i].tec|=(1<<(num-1));
}
int s0=(1<<s)-1,s1=0,s2=0,sum=0;
for(int i=0;i<m;i++)
{
int m0=t[i].tec&s0;
int m1=t[i].tec&s1;
s0^=m0;s1=(s1^m1)|m0;s2|=m1;
sum+=t[i].cost;
}
printf("%d\n",sum+DFS(m,s0,s1,s2));
}
return 0;
}