题解 P3212 【[HNOI2011]任务调度】
一个RP完全问题
当成dp想不出来,然后发现标签随机化233
枚举第三种任务先在A还是先在B,再随便贪心一下任务1,2的顺序,然后就是大力随机交换A,B机器任务执行的先后顺序,贪心计算时间,如果更优就保存,大概每次随机2000组够了
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 30;
const int inf = INT_MAX / 3;
int n, a[MAX_N], b[MAX_N], t[MAX_N], ans = inf;
int que_a[MAX_N], que_b[MAX_N], top_a, top_b;
bool flag[MAX_N];
int read()
{
int x = 0, f = 1; char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
bool cmp_a(int x, int y)
{
return b[x] == b[y] ? a[x] < a[y] : b[x] > b[y];
}
bool cmp_b(int x, int y)
{
return a[x] == a[y] ? b[x] < b[y] : a[x] > a[y];
}
int calc()
{
int sum_a = 0, sum_b = 0, re = 0;
for (int i = 1; i <= top_a; i++)
sum_a += a[que_a[i]];
for (int i = 1; i <= top_b; i++)
{
sum_b += b[que_b[i]];
if (sum_a > sum_b) sum_a += a[que_b[i]];
else sum_a = sum_b + a[que_b[i]];
}
re = max(sum_a, sum_b);
sum_a = sum_b = 0;
for (int i = 1; i <= top_b; i++)
sum_b += b[que_b[i]];
for (int i = 1; i <= top_a; i++)
{
sum_a += a[que_a[i]];
if (sum_b > sum_a) sum_b += b[que_a[i]];
else sum_b = sum_a + b[que_a[i]];
}
return max(re, max(sum_a, sum_b));
}
void solve()
{
top_a = top_b = 0;
for (int i = 1; i <= n; i++)
if (flag[i]) que_b[++top_b] = i;
else que_a[++top_a] = i;
sort(que_a + 1, que_a + top_a + 1, cmp_a);
sort(que_b + 1, que_b + top_b + 1, cmp_b);
int re = calc();
for (int cas = 1; cas <= 2000; cas++)
{
int a1, a2, b1, b2, tmp;
if (top_a)
swap(que_a[a1 = (rand() % top_a) + 1], que_a[a2 = (rand() % top_a) + 1]);
if (top_b)
swap(que_b[b1 = (rand() % top_b) + 1], que_b[b2 = (rand() % top_b) + 1]);
tmp = calc();
if (tmp < re) re = tmp;
else
{
if (top_a) swap(que_a[a1], que_a[a2]);
if (top_b) swap(que_b[b1], que_b[b2]);
}
}
if (re < ans) ans = re;
}
void dfs(int dep)
{
if (dep > n) solve();
else if (t[dep] == 1) flag[dep] = 0, dfs(dep + 1);
else if (t[dep] == 2) flag[dep] = 1, dfs(dep + 1);
else
{
flag[dep] = 0; dfs(dep + 1);
flag[dep] = 1; dfs(dep + 1);
}
}
int main()
{
srand(time(NULL) + 19260817);
n = read();
for (int i = 1; i <= n; i++)
t[i] = read(), a[i] = read(), b[i] = read();
dfs(1);
printf("%d\n", ans);
return 0;
}