题目大意:有一个学校要招老师,给你s门课,m个现役的老师,给你这m个老师分别教哪些课和他们的cost,现役的老师必须要继续留着,然后再给你n个应聘者,分别给你这n个人教哪些课和他们的cost,现在要求每门课至少要有两个老师教,问你最少的cost。
思路:基础的三进制的状态压缩DP吧,基本思想和二进制一样,只是这里需要多处理一下,用num[ i ][ j ] 表示数 i 如果用三进制表示,那么第 j 位为多少,设d[ s ] 表示状态s的最少花费,那么d[ s|si ] = min(d[ s ] +cost[ i ])。
在这里吐槽一下,这道题读入数据有点坑,没告诉你课的数目,我用的是先字符串读进去,再一个一个抠。。 = =
代码如下:
#include
#include
#include
using namespace std;
const int INF = 0x0fffffff ;
int my_pow(int x)
{
int s = 1;
for(int i =1;i<=x;i++)
s *= 3;
return s;
}
int num[22222][11];
void init()
{
memset(num,0,sizeof(num));
int s = my_pow(9);
for(int i = 1;i=3)
s += 2*tmp;
else s += (num[x][i]+num[y][i])*tmp;
tmp *= 3;
}
return s;
}
int d[22222] ;
char str[111];
int main()
{
init();
int s,m,n;
while(~scanf("%d%d%d",&s,&m,&n)&&s)
{
getchar();
int S = my_pow(s)-1;
for(int i = 0;i<=S;i++)
d[i] = INF;
int S0 = 0;
int sum = 0;
for(int i = 1;i<=m;i++)
{
gets(str);
for(int j = 0;str[j]!='\0';)
{
if(str[j]>='0'&&str[j]<='9')
{
int tmp = str[j]-'0';
j++;
while(str[j]>='0'&&str[j]<='9')
{
tmp = tmp*10 + str[j]-'0';
j++;
}
if(tmp>=100)
{
sum += tmp;
}
else
{
if(num[S0][tmp-1]<2)
S0 += my_pow(tmp-1);
}
}
else j++;
}
}
d[S0] = sum;
//printf("S0 = %d,sum = %d\n",S0,sum);
for(int i = 1;i<=n;i++)
{
emp[i].s = 0;
gets(str);
for(int j = 0;str[j]!='\0';)
{
if(str[j]>='0'&&str[j]<='9')
{
int tmp = str[j]-'0';
j++;
while(str[j]>='0'&&str[j]<='9')
{
tmp = tmp*10 + str[j]-'0';
j++;
}
if(tmp>=100)
{
emp[i].c = tmp;
}
else
{
emp[i].s += my_pow(tmp-1);
}
}
else j++;
}
}
for(int i = 0;i=0;j--)
{
int to = bin(j,emp[i+1].s,s);
d[to] = min(d[to],d[j]+emp[i+1].c);
//printf("i+1 =%d,d[%d] = %d\n",i+1,to,d[to]);
}
}
printf("%d\n",d[S]);
}
return 0;
}
/*
2 2 2
10000 1
20000 1
30000 1 2
40000 1 2
*/