题意:有一个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;
}
思路和我是一样的,我和它的不同只有第一步和有无公式。