1. 程式人生 > >CF115BLawnmower[貪心,模擬]

CF115BLawnmower[貪心,模擬]

inline code http \n 需要 tin for signed 執行

次優解祭

技術分享圖片
Cf的數據果然毒瘤, 一百多個點, 卡了我一晚上...
寫這道題的一點人生經驗 :

  • 細節題關鍵是一開始就要思路清晰, 把情況考慮全, 不能找到一個hack數據改一下, 改著改著代碼就成屎了
  • 實在是找不到錯因就別找了, 直接重構還快得多.
    這個題要註意的細節有:
  • [√] 可能有空行, j最左邊的草 = j最右邊的草=0, 導致爆炸
  • [√] 未考慮中間空多行的情況, 引用了空行(i-1 , i+1等)的草坐標(0), 導致爆炸
  • [√] 最後幾行都沒有草, 還是跳到了最後一行, 導致爆炸
  • [√] 沒嚴格執行奇數行只能向右走, 偶數行只能向左走, 導致爆炸
    ......
    打鉤表示我踩過這個坑

    解決方法: 記錄當前人的位置, 發現草再跳, 跳的時候在算距離(曼哈頓距離), 要跳到下一行前分需不需要在上一行跳額外的步數防止逆行兩種情況
#include<cstdio>
#define re register
#define in inline
int n,m;
char a[151][151];
int e[151][2];
in int abs(int x)
{
    return x>0?x:-x;
}
in int dis(int x1,int y1,int x2,int y2)
{
    return abs(x1-x2)+abs(y1-y2);
}
signed main()
{
    scanf("%d%d",&n,&m);
    for(re int i=1;i<=n;++i)
    {
        scanf("%s",a[i]+1);
        for(re int j=1;j<=m;++j)
        {
            if(a[i][j]==‘W‘){
                if(!e[i][0]) e[i][0]=j;
                e[i][1]=j;
            }
        }
    }//e[i][0]第i行最左邊草的坐標, e[i][1]最右邊的草
    int ans=0,nx=1,ny=1;//nx, ny: 當前位置
    if(e[1][0]) {ans+=dis(nx,ny,1,e[1][1]);ny=e[1][1];}
    for(re int i=1;i<n;++i)
    {
        if(!e[i+1][0]) continue;
        if(i&1){
            if(e[i+1][1]>=ny){
                ans+=dis(nx,ny,i+1,e[i+1][1]);//防止下一行逆行走的額外步數
                nx=i+1,ny=e[i+1][1];
                ans+=dis(nx,ny,i+1,e[i+1][0]);
                nx=i+1,ny=e[i+1][0];
            }
            else{
                ans+=dis(nx,ny,i+1,e[i+1][0]);
                nx=i+1,ny=e[i+1][0];
            }
        }
        else{
            if(e[i+1][0]<=ny){
                ans+=dis(nx,ny,i+1,e[i+1][0]);//防止下一行逆行走的額外步數
                nx=i+1,ny=e[i+1][0];
                ans+=dis(nx,ny,i+1,e[i+1][1]);
                nx=i+1,ny=e[i+1][1];
            }
            else{
                ans+=dis(nx,ny,i+1,e[i+1][1]);
                nx=i+1,ny=e[i+1][1];
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

CF115BLawnmower[貪心,模擬]