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 <bits/stdc++.h>
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; i<p; i++) {
x = a%3; y = b%3;
s += ((x+y)>2 ? 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;
}