洛谷-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
*/
posted @ 2017-11-03 18:20  Iamhx  阅读(470)  评论(0编辑  收藏  举报