1622

来源:互联网 发布:网络购物系统设计 编辑:程序博客网 时间:2024/06/13 05:32

  • 题目大意
  • 样例
    • input
    • output
    • 解释
  • 思路
  • 代码
  • Hit

题目大意

传送门

有一个m*n(1<=m,n<=10^5)的网格,每个格子里面都有一个机器人。每次可以发出如下4种命令之一:
NORTH SOUTH EAST WEST,作用是让所有的机器人都往相应的方向移动一格。如果一个机器人在执行某一命令之后走出的网格,那么就会立即炸毁。

给出4种指令的总条数(Cnorth,Csouth,Ceast,Cwest),求出一种指令顺序使得所有的机器人执行的命令条数之和最大。
炸毁的机器人不在执行命令。

样例

input

2 2
1 0 0 0
2 2
1 1 1 1
0 0

output

Case 1: 4
Case 2: 9

解释

思路

思路1:
先调整m和n的大小,保证m < n。
既然m < n,那么每次都对机器人下左右移动的命令。
先左还是先右,取决于向左的命令多还是向右的命令多:

  • 左右的命令分别是5和6,那么先向右,然后左右来5个循环,都用完。
  • 左右的命令分别是5和5,那么先左先右都可以,然后来四个循环,剩下一个命令。
  • 左右的命令分别是5和7,那么先向右,然后左右来5个循环,剩下一个向右的命令。

同理向上还是向下。

但是样例:
1 10
4 7 1 7
答案为67
这个先考虑左右移动,上下移动就不能移动,一旦移动,机器全没了。

所以我们考虑完左右移动之后,不能直接考虑上下,有可能不上下会更好。

在比如样例
5 9
5 10 4 2
答案为671
按照先左右移动算出答案为667,其实答案为671。
所以在 m < n的情况下,不一定先左右就是最优的。
也要考虑先上下。

我Debug中的样例都过了,最后还是wa。。。

代码

#include<cstdio>#include<map>#include<queue>#include<cstring>#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<stdlib.h>#include <math.h>#include <stack>using namespace std;#define  LL long longconst LL maxn = 5005;LL M,N;LL m,n;LL Cn,Cs,Ce,Cw;LL get_ans(LL Cn,LL Cs,LL Ce,LL Cw){        LL small_1 = min(Ce,Cw);        LL big_1 = max(Ce,Cw);        LL small_2 = min(Cn,Cs);        LL big_2 = max(Cn,Cs);        //printf("big_1:%d small_1:%d \n",big_1,small_1);        //printf("big_2:%d small_2:%d \n\n",big_2,small_2);        LL ans = 0;        LL sum1 = 0;        LL sum2 = 0;        LL sum3 = 0;        LL sum4 = 0;        //先左右移动,后上下移动        if(small_1>0)        {            sum1 += m*n;            big_1 -= 1;            if(small_1>big_1)            {                sum1 += m*(n-1)*(small_1+big_1);                big_1 = 0;                small_1 = 0;            }            else            {                sum1 += m*(n-1)*(min(small_1,big_1)*2);                LL temp =  min(small_1,big_1);                big_1 -= temp;                small_1 -= temp;            }            n--;        }        //printf("sum1: %d\n\n",sum1);        //上下移动还是不移动 判断两种:        //若不移动        LL tem_m = m;        LL tem_n = n;        LL tem_big_1 = max(big_1,small_1);        LL tem_big_2 = max(big_2,small_2);        while(tem_m && tem_n && tem_big_1)        {            if(tem_m>tem_n && tem_big_2>0)            {                swap(tem_m,tem_n);                swap(tem_big_1,tem_big_2);            }            sum4+=tem_m*tem_n;            tem_big_1--;            tem_n--;        }        while(tem_m && tem_n && tem_big_2)        {            sum4 += tem_m*tem_n;            tem_big_2--;            tem_m--;        }        //printf("sum4: %d\n\n",sum4);        //若移动        if(small_2>0)        {            sum2 += m*n;            big_2 -= 1;            if(small_2>big_2) {                sum2 += (m-1)*n*(small_2+big_2);                big_2 = 0;                small_2 = 0;            }            else            {                sum2 += (m-1)*n*(min(small_2,big_2)*2);                LL temp =min(small_2,big_2);                big_2 -= temp;                small_2 -= temp;            }            m--;        }        //printf("sum2 :%d\n\n",sum2);        big_1 = max(big_1,small_1);        big_2 = max(big_2,small_2);        //判断m和n的大小,伺机而动        while(m&&n&&big_1)        {            if(m>n&&big_2>0) //保证每次都是m<=n            {                swap(m,n);                swap(big_1,big_2);            }            sum3+=m*n;            big_1--;            n--;        }        while(m&&n&&big_2)        {            sum3+=m*n;            big_2--;            m--;        }        //printf("sum3 :%d\n",sum3);        ans = sum1 + max(sum4,sum2+sum3);}int main(){    LL Casenum=1;    while(~scanf("%lld%lld",&M,&N))    {        if(M==0 && N==0) break;        scanf("%lld %lld %lld %lld",&Cn,&Cs,&Ce,&Cw);        m = M;        n = N;        LL ans1 = get_ans(Cn,Cs,Ce,Cw);        m = N;        n = M;        LL ans2 = get_ans(Ce,Cw,Cn,Cs);        //printf("ans1 %d ans2 %d\n\n",ans1,ans2);        printf("Case %lld: %lld\n",Casenum++,max(ans1,ans2));    }}/*https://www.udebug.com/UVa/1622*/

Hit

原创粉丝点击