产品报告
对于B[i]降序排列是显而易见的,因为将最大的冷却时间放在最后,才会是最优的(本来写的贪心, 结果和zs大佬交流后发现我题意立即错了)。
使用DP的原因是冷却时间在第一个机器和在第二个机器的分配不同,导致最后的答案不同。
\(f[i][j]\) 表示第一个机器在处理前 \(i\) 个产品花费j时间时,总的时间花费的最小值。(\(f[i][j]\) 包括了最后的冷却时间) , 所以第二个机器的花费可以算出来,总的
花费就是上面两个取最小值。
对于第一台机子:\(f[i][j] = min( f[i][j], max(f[i - 1][j - a[i]],j + b[i] )\), (如果上一个的冷却时间超级长,就是第一个,否则是第二个)对于第二台机子 : \(f[i][j] = min ( f[i][j], max( f[i - 1][j] , sum[i] - j + b[i])\)( \(i\) 位不由第一台机子处理因此是f[i - 1][j],剩下的由第二台处理)。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LOCAL
const int maxn = 210;
int n;
int sum[maxn], f[maxn][maxn * maxn];
int max (int x, int y) {
return x > y ? x : y;
}
int min (int x, int y) {
return x < y ? x : y;
}
struct Product {
int a, b;
};
Product pro[maxn];
bool cmp (Product pro1, Product pro2) {
return pro1.b > pro2.b;
}
inline void DP() {
for (int i = 0; i <= n; ++ i)
for (int j = 0; j <= maxn * maxn - 1; ++ j)
f[i][j] = maxn * maxn + 10;
f[0][0] = 0;
for (int i = 1; i <= n; ++ i) {
for (int j = 0; j <= sum[i]; ++ j) {
if (j >= pro[i].a) {
f[i][j] = min(f[i][j], max(f[i - 1][j - pro[i].a], j + pro[i].b));
}
if (sum[i] - j + pro[i].b >= 0) {
f[i][j] = min(f[i][j], max(f[i - 1][j], sum[i] - j + pro[i].b));
}
}
}
int ans = 0x7fffffff - 1;
for (int i = 1; i <= sum[n]; ++ i) {
ans = min(f[n][i], ans);
}
printf("%d\n", ans);
}
inline void init() {
#ifdef LOCAL
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; ++ i) {
scanf("%d%d", &pro[i].a, &pro[i].b);
}
std::sort(pro + 1, pro + n + 1, cmp);
for (int i = 1; i <= n; ++ i)
sum[i] = sum[i - 1] + pro[i].a;
}
int main() {
init();
DP();
return 0;
}
分球
这道题非常简单,要么用数学方法算一下排列组合,要么就自己打一个递推,只是需要用高精度。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 110;
const int maxm = 100;
int n,m;
struct Bignum {
int dig[maxn];
int len;
Bignum() {
memset(dig,0,sizeof(dig));
len = 1;
}
};
Bignum F[maxn][maxn];
inline Bignum Plus(Bignum a, Bignum b) {
for (int i = 1; i <= b.len; ++ i) {
a.dig[i] += b.dig[i];
}
for (int i = 1; i <= max(a.len,b.len) + 1; ++ i) {
a.dig[i + 1] += a.dig[i] / 10;
a.dig[i] %= 10;
}
int k = maxm - 1;
while(a.dig[k] == 0) k --;
a.len = k;
return a;
}
inline Bignum Mul(Bignum a, int b) {
for (int i = 1; i <= a.len; ++ i) {
a.dig[i] *= b;
}
for (int i = 1; i <= maxm - 3; ++ i) {
a.dig[i + 1] += a.dig[i] / 10;
a.dig[i] %= 10;
}
int k = maxm - 1;
while(a.dig[k] == 0) k --;
a.len = k;
return a;
}
inline void Print(Bignum a) {
for (int i = a.len; i >= 1; -- i) {
cout << a.dig[i];
}
putchar('\n');
}
inline void solve() {
for (int i = 1; i <= maxn - 1; ++ i) {
for (int j = 1; j <= maxn - 1; ++ j) {
if ( i == j ) F[i][j].dig[1] = 1, F[i][j].len = 1;
else if ( i > j ) {
F[i][j] = Plus(Mul(F[i - 1][j],j),F[i - 1][j - 1]);
}
}
}
}
int main() {
freopen("ball.in","r",stdin);
freopen("ball.out","w",stdout);
int N,M;
F[0][0].dig[1] = 1, F[0][0].len = 1;
solve();
while(cin >> N >> M) {
if (N < M) cout << 0 << endl;
else if (N == M) cout << 1 << endl;
else Print(F[N][M]);
}
}
地图
dfs标记联通块
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 1010;
bool map[maxn][maxn];
int ans = 0;
int n,m;
int dx[5] = {0,1,-1,0,0};
int dy[5] = {0,0,0,1,-1};
inline void DFS(int x, int y) {
map[x][y] = 0;
for (int i = 1; i <= 4; ++ i) {
int nowx = x + dx[i];
int nowy = y + dy[i];
if (map[nowx][nowy]){
DFS(nowx,nowy);
}
}
}
int main() {
freopen("map.in","r",stdin);
freopen("map.out","w",stdout);
cin >> n >> m;
for (int i = 1; i <= n ; ++ i) {
for (int j = 1; j <= m; ++ j) {
char x;
cin >> x;
if(x == 'X') map[i][j] = 1;
else map[i][j] = 0;
}
}
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= m; ++ j) {
if(map[i][j]) {
DFS(i,j);
ans ++;
}
}
}
cout << ans;
}
坐标变换
这道题要用到Graham的一点知识,还有关于凸包的一点小小的常识,用dp求出每一个点,就OK了。新建的n + 1 这个点是为了保证最后围成封闭。
然后感谢lcc大佬的帮助。
#include <cstdio>
#include <algorithm>
#define LOCAL
const int maxn = 105;
int f[maxn][maxn];
struct Point {
int x, y;
};
Point map[maxn];
int n, ans = 0;
int max (int a, int b) {
return a > b ? a : b;
}
bool cmp (Point a, Point b) {
return ((double) a.y / a.x) < ((double) b.y / b.x);
}
inline bool check(int a, int b, int c) {
int tmp = 0;
tmp += map[a].x * map[b].y;
tmp += map[a].y * map[c].x;
tmp += map[b].x * map[c].y;
tmp -= map[b].y * map[c].x;
tmp -= map[c].y * map[a].x;
tmp -= map[b].x * map[a].y;
return tmp < 0;
}
inline void init() {
#ifdef LOCAL
freopen("polygon.in","r",stdin);
freopen("polygon.out","w",stdout);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; ++ i) {
scanf("%d%d", &map[i].x, &map[i].y);
f[i][0] = 1;
}
std::sort(map + 1, map + n + 1, cmp);
map[0].x = 0, map[0].y = 0;
map[n + 1].x = map[n + 1].y = 0;
}
inline void DP() {
for (int i = 2; i <= n + 1; ++ i) {
for (int j = 1; j < i; ++ j) {
f[i][j] = 0;
for (int k = 0; k < j; ++ k) {
if (check(i, j, k)) {
f[i][j] = max(f[i][j], f[j][k] + 1);
}
}
}
}
ans = 0;
for (int i = 1; i <= n; ++ i) {
ans = max(ans, f[n + 1][i]);
}
printf("%d\n", ans);
}
int main() {
init();
DP();
}