直接放图吧:
这是我第一次写的代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, mac[10001], Time[10001], ans = INT_MAX / 3, Min = INT_MAX / 3, Now = 0;
int SetNow() {
int k = 0;
for (int i = 1; i <= m; i++) k = max(k, mac[i]);
return k;
}
void Dfs(int d) {
if (d == n + 1) {
Min = 0;
for (int i = 1; i <= n; i++) Min = max(Min, mac[i]);
ans = min(ans, Min);
return;
}
for (int i = 1; i <= m; i++) {
mac[i] += Time[d];
Now = SetNow();
if (Now >= ans)
return;
Dfs(d + 1);
mac[i] -= Time[d];
}
}
bool Compare(int a, int b) { return a > b; }
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> Time[i];
sort(Time + 1, Time + n + 1, Compare);
Dfs(1);
cout << ans;
}
洞可能有些多,一步步慢慢来:
这一段→→→
int SetNow() {
int k = 0;
for (int i = 1; i <= m; i++) k = max(k, mac[i]);
return k;
}
能否优化?
因为我们发现,当时更新的只是mac[i]
,所以只要比较mac[i]
即可。
#include <bits/stdc++.h>
using namespace std;
int n, m, mac[10001], Time[10001], ans = INT_MAX / 3, Min = INT_MAX / 3, Now = 0;
void Dfs(int d) {
if (d == n + 1) {
Min = 0;
for (int i = 1; i <= m; i++) Min = max(Min, mac[i]);
ans = min(ans, Min);
return;
}
for (int i = 1; i <= m; i++) {
mac[i] += Time[d];
Now = max(Now, Time[d]);
if (Now >= ans)
return;
Dfs(d + 1);
mac[i] -= Time[d];
Now = min(Now, Time[d]);
}
}
bool Compare(int a, int b) { return a > b; }
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> Time[i];
sort(Time + 1, Time + n + 1, Compare);
Dfs(1);
cout << ans;
}
继续看:
Now = max(Now, Time[d]);
if (Now >= ans)
return;
Dfs(d + 1);
mac[i] -= Time[d];
Now = min(Now, Time[d]);
Now
实质上是不可逆的,例如:
mac[1] | mac[2] | Now | Time[i] |
---|---|---|---|
10 | 2 | 10 | 20 |
经过:
Now = max(Now, Time[d]);
更新:
mac[1] | mac[2] | Now | Time[i] |
---|---|---|---|
10 | 22 | 22 | 20 |
再经过:
Now = min(Now, Time[d]);
却变成了
mac[1] | mac[2] | Now | Time[i] |
---|---|---|---|
10 | 2 | 2 | 20 |
所以我们要一个临时变量保存。
if (Now >= ans)
return;
难道放在mac[i]
不成立,后面的机器都被抛弃了吗?
剪枝:
for (int i = 1; i <= m; i++) Min = max(Min, mac[i]);
其实与上一个道理是一样的,只要传一个参数,每次记录最大,最大…最后ans
再选最小。
修改:
#include <bits/stdc++.h>
using namespace std;
int n, m, mac[10001], Time[10001], ans = INT_MAX / 3;
void Dfs(int d, int Now) {
if (d == n + 1) {
ans = min(ans, Now);//剪枝
return;
}
int New;
for (int i = 1; i <= m; i++) {
mac[i] += Time[d];
New = max(Now, mac[i]);//洞洞1
if (New >= ans) {
mac[i] -= Time[d];//洞洞2
continue;
}
Dfs(d + 1, New);
mac[i] -= Time[d];
}
}
bool Compare(int a, int b) { return a > b; }
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> Time[i];
sort(Time + 1, Time + n + 1, Compare);
Dfs(1, 0);
cout << ans;
}
AC。