洛谷-P2198 杀蚂蚁

Posted 小菜猫的家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷-P2198 杀蚂蚁相关的知识,希望对你有一定的参考价值。

Solution

大致感受一下,我们就可以发现似乎激光塔一定要放在最末尾才能最大化一个激光塔给蚂蚁的伤害,所以所有的激光塔我们强制全部放在最末尾.然后呢,我们需要把前面的多余空位合理安排给放射塔和激光塔,这个过程可以用DP来解决,大致就是设F[i][j] 表示前i+j格空位放置i座干扰塔,j座放射塔给蚂蚁带来的最大伤害.没了.

f[i][j]=max(f[i - 1][j] + g * j * b * k,f[i][j - 1] + g * (b * i + t) * k)

好,但是由于数据实在太大,所以要加上复杂的高精度,嗯,大概就是要写高精乘高精,高精乘低精,高精减低精,高精加高精,高精加低精,高精度数大小比较等等,不过没事,也就几行...

#include<bits/stdc++.h>
using namespace std;
const int mo = 100000000, maxn = 1055;
struct node{
	long long w[30];
	inline void operator += (long long x){
		w[1] += x; int i = 1;
		while (w[i] >= mo) w[i] -= mo, ++ w[++i];
		if (i > w[0]) w[0] = i;
	}
};

inline node operator + (node a, node b){
	for (int i = 1; i <= b.w[0]; ++i) a.w[i] += b.w[i];
	a.w[0] = max(a.w[0], b.w[0]);
	for (int i = 1; i <= a.w[0]; ++i) if (a.w[i] >= mo) a.w[i] -= mo, ++ a.w[i + 1];
	if (a.w[a.w[0] + 1]) ++ a.w[0];
	return a;
}

inline node operator * (node a, node b){
	node c; memset(c.w, 0, sizeof(c.w)); 
	for (int i = 1; i <= a.w[0]; ++i) 
	for (int j = 1; j <= b.w[0]; ++j) c.w[i + j - 1] += a.w[i] * b.w[j];
	c.w[0] = a.w[0] + b.w[0] - 1;
	for (int i = 1; i <= c.w[0]; ++i) if (c.w[i] >= mo) c.w[i + 1] += c.w[i] / mo, c.w[i] %= mo;
	while (c.w[c.w[0] + 1]) ++ c.w[0];
	return c;
}

inline node operator * (node a, long long x){
	for (int i = 1; i <= a.w[0]; ++i) a.w[i] *= x;
	for (int i = 1; i <= a.w[0]; ++i) if (a.w[i] >= mo) a.w[i + 1] += a.w[i]/mo, a.w[i] %= mo;
	if (a.w[a.w[0] + 1]) ++ a.w[0];
	return a;
}

inline node operator - (node a, node b){
	for (int i = 1; i <= b.w[0]; ++i) a.w[i] -= b.w[i];
	for (int i = 1; i <= a.w[0]; ++i) if (a.w[i] < 0) a.w[i] += mo, -- a.w[i + 1];
	while (a.w[0] > 0 && !a.w[a.w[0]]) -- a.w[0];
	return a;
}

inline bool operator < (node a, node b){
	if (a.w[0] != b.w[0]) return a.w[0] < b.w[0];
	for (int i = a.w[0]; i; --i) if (a.w[i] != b.w[i]) return a.w[i] < b.w[i];
	return false;
}

inline void read(node &a){
	char s[300]; memset(a.w, 0, sizeof(a.w));
	scanf("%s", s); int m = strlen(s);
	int x,j,i;
	for (x = 0, j = 1, i = m - 1; ~i; --i, j *= 10){
		if (j == mo) j = 1, a.w[++a.w[0]] = x, x = 0;
		x += (s[i] - \'0\') * j;
	}
	if (x) a.w[++ a.w[0]] = x;
	if (!a.w[0]) a.w[0] = 1;
}

inline void print(node a){
	printf("%lld", a.w[a.w[0]]);
	for (int i = a.w[0] - 1; i > 0; --i){
		for (int j = 10; j < mo; j *= 10) if (a.w[i] < j) putchar(\'0\');
		printf("%lld", a.w[i]);
	}
	puts("");
}

long long n;
node  r, g, b, t;
node f[maxn][maxn], ans; 

inline node max(node a, node b){
	return a < b ? b : a;
}

int main(){
	scanf("%lld", &n);
	read(r); read(g); read(b); read(t);
	//return 0;
	for (long long i = 1; i <= n; ++i) f[0][i] = f[0][i - 1] + g * t * (n - i);	
	for (long long i = 1; i < n; ++i) 
	for (long long j = 1, k; k = n - i - j; ++j)
	f[i][j] = max(f[i - 1][j] + g * j * b * k, 
	// b * k Ϊ¼ÓÁËÒ»×ù¸ÉÈÅËþºó¶à³öµÄʱ¼ä, g * j Ϊj×ù·ÅÉäËþµÄÉ˺¦. 
				  f[i][j - 1] + g * (b * i + t) * k);
	// Õâ×ùмӵķÅÉäËþÔì³ÉµÄÉ˺¦ÊÇ g, ´Ëʱÿ¸ñ³ÖÐøµÄʱ¼äΪ i * b + t, ¹²ÓÐk¸ñ,ÄÇô
	// É˺¦Îª g * (i * b + t) * k
	for (long long i = 0; i <= n; ++i) 
	for (long long j = 0; j <= n - i; ++j) {
		long long k = n - i - j; if (k < 0) continue;
		ans = max(ans, f[i][j] + (t + b * i) * k * r);
	}
	print(ans);				
	return 0;
}
/*
400 2147483647 2147483647 2147483647 1000
*/

以上是关于洛谷-P2198 杀蚂蚁的主要内容,如果未能解决你的问题,请参考以下文章

Luogu2586 [ZJOI2008]杀蚂蚁 ---- 模拟

P2586 [ZJOI2008]杀蚂蚁(模拟)

《杀蚂蚁》有感

P2586 [ZJOI2008]杀蚂蚁

[ZJOI2008]杀蚂蚁

[ZJOI2008]杀蚂蚁antbuster