浙江十套 - 第八套 - 解题报告

产品报告

对于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();
}
posted @ 2018-06-06 20:27  AlessandroChen  阅读(177)  评论(0编辑  收藏  举报