uva 10817 状压dp

UVA 10817 - Headmaster's Headache


学校要安排s个课程的教师,每个课程至少有两门老师任课,已知学校现有现有的n位老师的工资和任课情况,和m为前来应聘的老师的薪资和任课情况,求出安排全部课程的最少薪资花费。不得开除现有老师。


状压dp
dp[i][s] 表示前i位老师在课程安排为s的情况下的最小花费。s存放所有课程的安排情况。是个三进制数,每位的0表示没有老师任课,1表示有一位老师任课,2表示大于一位老师任课。_s表示s下安排第i+1位老师后的状态。

dp[i+1][_s] = min(dp[i+1][_s], dp[i][s]);

吐槽这GB的输入。。。


#include 

using namespace std;

const int INF = 999999999;

struct Node {
	int p;
	int s;
	Node():p(0), s(0){}
	Node(int _p, int _s):p(_p),s(_s){}
}t[105];

int p, n, m;
int dp[7000];
char s[10000]; 
int _pow(int n, int p) {
	int res = 1;
	while (p) {
		if (p&1) res *= n;
		n *= n;
		p >>= 1;
	}
	return res;
}

Node _getData() {
	Node _tmp;

	gets(s);// puts(s);
	int _len = strlen(s);
	int i=0, res = 0;

	while (s[i] >= '0' && s[i] <= '9' && i < _len) {
		res = res*10 + s[i] - '0';
		i++;
	}

	_tmp.p = res;
	
	int k=0;
	while (i < _len) {
		if (s[i] >= '0' && s[i] <= '9') {
			_tmp.s += _pow(3, s[i]-'0'-1);
		}
		i++;
	}
	return _tmp;
}

int unio (int a, int b) {
	int x=0, y=0, s=0;
	for (int i=0; i2 ? 2 : x+y) * _pow(3, i);
		a /= 3; b /= 3;
	}
	return s;
}

int _sum, S;

int main () {
	for (; gets(s); ) {
		// cout << p << " " << m << " " << n << endl;

		sscanf(s, "%d%d%d", &p, &n, &m);
		if (p == 0) break;
		
		_sum = 0; S = 0;

		for (int i=1; i<=n; i++) {
			t[i] = _getData();
			_sum += t[i].p;
			S = unio(S, t[i].s);
		}
		// cout << _sum << " " << S << endl;
		for (int i=1; i<=m; i++) {
			t[i] = _getData();
		}
		// for (int i=2; i<=m; i++) 
		// 	cout << t[i].p << endl;

		for (int s=0; s<_pow(3, p); s++) dp[s] = INF; dp[S] = _sum;

		for (int i=1; i<=m; i++) {
			for (int s=_pow(3, p)-1; s>=S ; s--) {
				int g = unio(s, t[i].s);
				if (g < _pow(3, p)) dp[g] = min(dp[g], dp[s]+t[i].p);
			}
		}

		cout << dp[_pow(3, p)-1] << endl;
	}
	return 0;
}


你可能感兴趣的:(dp)