码迷,mamicode.com
首页 > 其他好文 > 详细

例题9-15 校长的烦恼 UVa10817

时间:2015-02-16 17:02:01      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:uva   动态规划   

1.题目描述:点击打开链接

2.解题思路:本题利用集合上的动态规划解决。定义集合s1表示恰好有一个人教的课程,集合s2表示至少有两个人教的课程。定义d(i,s1,s2)表示已经考虑了前i个人时的最小花费(人物编号从0开始)。则不难写出状态转移方程:

d(i,s1,s2)=min{d(i+1,s1‘,s2‘)+c[i],d(i+1,s1,s2)};

上式中只有当i≥m时才会考虑第二项。对于这个方程的理解,重点在s1,s2集合的变化,随着s2集合不断扩大,花费的资金也应当越少,当s2恰好等于所有科目的集合时,不需要花钱,i只是对阶段的描述。其实这也不难理解,没有一个教师来教书的时候(即i=0时),肯定是学校要花钱最多的时候,当所有的教师都应聘完毕了,课程都有人教了,自然花费就少了。

本题的一个重要技巧就是利用位运算来解决各种集合之间的关系,另外一个小技巧就是设置一个辅助的参数s0,来方便集合之间的运算:将d(i,s1,s2)改为d(s0,s1,s2),其中s0表示没有任何人能教的科目的集合。对于方程中s1‘,s2‘的计算,详见代码。注意:由于本题中的课程是从1开始编号的,而集合中是从0开始处理的,因此在输入时要预处理。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

const int maxn = 120+10;
const int maxs = 8 + 1;
#define INF 100000000
int m, n, s;
int c[maxn], st[maxn];//数组c表示工资,st表示第i个老师教课的集合
int d[maxn][1 << maxs][1 << maxs];

int dp(int i, int s0, int s1, int s2)
{
	if (i == m + n)
		return s2 == (1 << s) - 1 ? 0 : INF;//如果s2恰好等于全部课程的集合时,已经满足题意,不需要花钱
	int&ans = d[i][s1][s2];
	if (ans >= 0)return ans;
	ans = INF;
	if (i >= m)ans = dp(i + 1, s0, s1, s2);//不选第i个应聘者,由于选i应聘者会导致s0,s1,s2改变,因此先初始化成不选
	int m0 = st[i] & s0;//只有第i个应聘者会教的课程
	int m1 = st[i] & s1;//第i个应聘者也会教的课程
	s0 ^= m0;//在s0集合中除去所有只有i应聘者会教的课程,即m0
	s1 = (s1^m1) | m0;//m1代表的所有课程变为了至少两个人会教,从s1中除去,同时加上m0
	s2 |= m1;//将m1添加到s2
	ans = min(ans, c[i] + dp(i + 1, s0, s1, s2));//选第i个应聘者,取较小者
	return ans;
}

int main()
{
	//freopen("test.txt", "r", stdin);
	while (~scanf("%d%d%d", &s, &m, &n) && s&&m&&n)
	{
		memset(d, -1, sizeof(d));
		memset(st, 0, sizeof(st));
		memset(c, 0, sizeof(c));
		getchar();
		for (int i = 0; i < m + n; i++)
		{
			string str;
			getline(cin, str);
			stringstream ss(str);
			int x,flag=1;
			while (ss >> x)
			{
				if (flag){ flag = 0; c[i] = x; }
				else
				{
					x--;
					st[i] |= (1<<x);
				}
			}
		}
		int ans = dp(0, (1 << s) - 1, 0, 0);
		printf("%d\n", ans);
	}
	return 0;
}

例题9-15 校长的烦恼 UVa10817

标签:uva   动态规划   

原文地址:http://blog.csdn.net/u014800748/article/details/43852001

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!