您的位置:首页 > 其它

UVA 10817 Headmaster's Headache [动态规划] [状压dp]

2016-08-28 08:51 483 查看
Headmaster’s Headache

Time Limit: 3000MS 64bit IO Format: %lld & %llu





状压dp。

最终要让每个科目有至少两人教,那么可以用S2表示可以两人及以上的人教的课程集合,类似地,转移更新时用S1表示只有恰好一人的集合,S0表示没有人教的集合。

注意三者之间的转移更新!!要彼此分离开。。。

表示状态只需要其中两个即可,因为剩下一个是唯一确定的。

此题用递归优化时间复杂度,避开不可能的集合状态。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
const int INF=0x3f3f3f3f;
const int maxn = 125;
const int maxs = 10;
struct Teacher
{
int cost;
int status;
Teacher(){cost=status=0;}
}teach[maxn];
int sub,m,n;
char s[maxn];
int dp[maxn][1<<maxs][1<<maxs];
inline bool init()
{
if(!~scanf("%d%d%d",&sub,&m,&n) || !(n&&m&&sub)) return false;
memset(dp,0,sizeof(dp));
memset(teach,0,sizeof(teach));
for(int i=1;i<=n+m;i++)
{
scanf("%d",&teach[i].cost);
gets(s);
int lens=strlen(s);
for(int j=0;j<lens;j++) if(isdigit(s[j])) teach[i].status|=(1<<(s[j]-'0'-1));
}
return true;
}
int f(int k,int S1,int S2)
{
if(!k) return S2^((1<<sub)-1)? INF : 0;
int &ans = dp[k][S1][S2];
if(ans) return ans;
int s=teach[k].status;
ans=INF;
if(k>m) smin(ans,f(k-1,S1,S2));
int S0=((1<<sub)-1)^(S1|S2);
int t0=s&S0,t1=s&S1;
S0^=t0; S1=(S1^t1)|t0; S2|=t1;
smin(ans,f(k-1,S1,S2)+teach[k].cost);
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("head.in","r",stdin);
freopen("head.out","w",stdout);
#endif
while(init())
{
int ans = f(n+m,0,0);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 状压dp