UVA1622

题意:有一个n*m的网格,每个格子里有一个机器人,每次可以发出north,south,east,west,指令,使得所有机器人朝一个方向移动,走出网格就不能继续执行指令,求出机器人的最大指令执行数量。

分析:题目不难,但是要考虑的因素有很多,很可能考虑不周全。

想出来要先判断走东西还是南北,并且要模拟走东西和南北那个走的次数总和最大,这个模拟不能直接算出上下或左右最少的走完了的数量,因为它下面还有一个判断,是判断上下方向或左右方向只剩下一个单方向,然后判断另一个双方向的情况。

#include<iostream>
#include<string.h>
#include<sstream>
#include<set>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<math.h>
using namespace std;
typedef long long ll;
int judge(ll n,ll s,ll curm,ll curn) {
	ll ans = 0, hi;
	if (min(n, s) == 0 && max(n, s) > 0) {
		ans += curm * curn;
		hi = max(n, s) - 1;
	}
	else if (min(n, s) > 0) {
		ans += curm;
		ans += (min(n, s) * 2 * curm*(curn - 1));
		hi = abs(n - s);
		if (n != s) { ans += curm * (curn - 1); hi--; }
		curn--;
	}
	return ans;
}
int main() {
	
	ll N, M;int kase = 0;
	while (cin >> N >> M) {
		ll n, s, w, e;
		ll ans = 0;
		ll curn, curm;
		cin >> n >> s>>w>>e;
		
		ll hi=0, we=0;
		int k1 = judge(n, s, M, N), k2 = judge(w, e, N, M);
		if (( k1> k2)||(k1==k2&&N>M)) {
			swap(N, M);
			swap(n, w);
			swap(s, e);
		}
		curn = N, curm = M;
		if (min(e, w) == 0&&max(e,w)>0) {
			ans += curn * curm;
			we = max(w, e) - 1;
			curm--;
		}
		else if(min(e,w)>0){
			ans += curn;
			ans += (min(e, w) * 2 * (curm-1)*curn);
			we = abs(e - w);
			if (e != w) { ans += (curm-1)*curn; we--; }
			curm--;
		}
			while ((curm*curn+judge(n,s,curm-1,curn))>(judge(n,s,curm,curn)+(curn-1)*curm)&&we>0) {
				ans += curm * curn;
				curm--;
				we--;
			}
			//if (curm <= curn||we<=0) {
				if (min(n, s)==0&&max(n,s)>0) {
					ans += curm * curn;
					hi = max(n, s) - 1;
					curn--;
				}
				else if(min(n,s)>0){
					ans += curm;
					ans += (min(n, s) * 2 * curm*(curn - 1));
					hi = abs(n - s);
					if (n != s) { ans += curm * (curn - 1); hi--; }
					curn--;
				}
			//}
			while(curm<curn&&hi>0) {
				ans += curm * curn;
				curn--;
				hi--;
			}
			
		
		while ((hi > 0 || we > 0)&&curn>0&&curm>0) {
			ans += curn * curm;
			if ((curn > curm&&hi) || !we) {
				curn--; hi--;
			}
			else {
				we--; curm--;
			}
		}
		cout << "Case "<<++kase<<": "<<ans << endl;

	}
	return 0;
}

第一步判断错了,不想写了,重写还要再加个函数。

ac代码:


#include<cstdio>

#include<algorithm>

#define REP(i, a, b) for(int i = (a); i < (b); i++)

using namespace std;

typedef long long ll;

 

ll solve(ll x, ll y, ll n, ll s, ll w, ll e)

{

	ll res = 0;

	if(s > n) swap(s, n);

	if(e > w) swap(e, w);

	

	if(n)   //东西来回 

	{

		res += x * y;

		x--; n -= s;

		if(n) res += x * y * s * 2, n--;

		else res += x * y * (s * 2 - 1);

		s = 0;

	}

	

	if(w)  //判断向南北还是向西 

	{

		w -= e;

		if(w) e *= 2, w--;

		else e = e * 2 - 1;

		while((1 - y) * e >= y - x && n) //两串很长的公式最后的化简结果 

		{

			res += x * y;

			n--; x--;

		}

		res += x * y; y--;

		res += x * y * e; e = 0;

	}

	

	while(x * y > 0 && n + w > 0)  //剩下的处理掉 

	{

		res += x * y;

		if((x > y && n) || !w) n--, x--;

		else w--, y--;

	}

	

	return res;

}

 

int main()

{

	int kase = 0;

	ll x, y, n, s, w, e; //要开long long 

	while(~scanf("%lld%lld", &x, &y) && x && y)

	{

		scanf("%lld%lld%lld%lld", &n, &s, &w, &e);

		ll res = max(solve(x, y, n, s, w, e), solve(y, x, e, w, n, s)); //两种情况都做一遍取最大 

		printf("Case %d: %lld\n", ++kase, res);

	}

	return 0;

}

思路和我是一样的,我和它的不同只有第一步和有无公式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值