您的位置:首页 > 其它

UVA 10817 Headmaster's Headache

2013-08-03 19:49 344 查看
题目大意:有一个学校要招老师,给你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<cstdio>
#include<cstring>
#include<algorithm>
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<s;i++)
{
int t = i;
for(int j = 0;t;j++)
{
num[i][j] = t%3;
t/=3;
}
}
}

struct Emp
{
int c;
int s;
Emp(){ s = 0;}
} emp[111];

int bin(int x,int y,int lim)
{
int tmp = 1;
int s = 0;
for(int i = 0;i<lim;i++)
{
if(num[x][i]+num[y][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<n;i++)
{
for(int j = S;j>=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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: