uva 10817 Headmaster's Headache 状压dp

来源:互联网 发布:纹理算法 编辑:程序博客网 时间:2024/05/22 03:15
//uva 10817 Headmaster's Headache 状压dp////解题思路:////因为数据范围很小,所以想到状压dp。////dp(i,s1,s2) 表示到前i个人,已经一门课只有一个老师教的集合//为s1,一门课有两个老师教的集合为s2.则状态转移为////dp(i,s1,s2) = min(dp(i+1,s1,s2),dp(i+1,s1',s2'))//前一项表示不聘用,后一项表示聘用,则s1'表示最新的只有一个//老师教的集合,s2'表示最新的有两个老师教的集合。////最后的结果当然就是d(1,0,0);////为了更加方便的实现,加入一个s0表示没有老师教的集合。//dp(i,s0,s1,s2);////在算新的s0,s1,s2时,定义一个m0,和一个m1表示加入该位教师//分别有一个老师,和两个老师教的集合//m0 = s0 & se[i];//m1 = s1 & se[i];////s0 = s0 | m0;////s1 = (s1 ^ m1) | m0;////s2 = s2 | m1;#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 200;const int INF = 0x1f1f1f1f;int S,M,N;int w[MAXN];int se[MAXN];int d[200][1<<9][1<<9];bool vis[200][1<<9][1<<9];inline bool isn(char c){if (c >= '0' && c <= '9')return true;return false;}void input(){for (int i=1 ;i <= M + N;i++){scanf("%d",&w[i]);char s[30];gets(s);int n = strlen(s);se[i] = 0;for (int j=0;j<n;j++){if (isn(s[j])){se[i] |= (1<<(s[j] - '0'-1));}}}}int DP(int i,int s0,int s1,int s2){if (i == M + N + 1)return  s2 == (1<<S) - 1 ? 0 : INF;if (vis[i][s1][s2])return d[i][s1][s2];vis[i][s1][s2] = 1;int& ans = d[i][s1][s2];ans = INF;if (i > M)ans = min(ans,DP(i+1,s0,s1,s2));int m0 = s0 & se[i];int m1 = s1 & se[i];s0 ^= m0;s1 = (s1 ^ m1) | m0;s2 |= m1;ans = min(ans,DP(i+1,s0,s1,s2) + w[i]);return ans;}void solve(){memset(vis,0,sizeof(vis));printf("%d\n",DP(1,(1<<S)-1,0,0));}int main(){//freopen("1.txt","r",stdin);while(scanf("%d%d%d",&S,&M,&N)!=EOF){if (S==0)break;input();solve();}return 0;}

0 0
原创粉丝点击