zoukankan      html  css  js  c++  java
  • 【CF1247E】Rock Is Push(DP,二分)

    题意:有一个n*m的方格,每一格可能为空也可能有石头,要从(1,1)走到(n,m),每次可以往右或往下走

    每次走的时候都会将自己面前的所有石头向移动方向推一格,如果碰到了边界就推不过去

    问方案数模1e9+7

    n,m<=2e3

    思路:设dp[i][j][0/1]分别为当前走到(i,j),上一次从左/上走的合法方案数

    合法的转移是行坐标或列坐标连续的一段,而且受障碍物个数和当前行/列号限制

    写出式子之后可以发现决策范围对于i相同或者j相同是单调的,可以用队列维护,但显然二分更好写

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 //typedef pair<ll,ll>P;
     12 #define N  2010
     13 //#define M  200010
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 char ch[N];
     35 ll dp[N][N][2],s[N][N][2];
     36 int b[N][N];
     37 
     38 int read()
     39 {
     40    int v=0,f=1;
     41    char c=getchar();
     42    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     43    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     44    return v*f;
     45 }
     46 
     47 int calcb(int x1,int y1,int x2,int y2)
     48 {
     49     return b[x2][y2]-b[x1-1][y2]-b[x2][y1-1]+b[x1-1][y1-1];
     50 }
     51 
     52 ll calc(int x1,int y1,int x2,int y2,int op)
     53 {
     54     ll res=s[x2][y2][op]-s[x1-1][y2][op]-s[x2][y1-1][op]+s[x1-1][y1-1][op];
     55     res=(res%MOD+MOD)%MOD;
     56     return res;
     57 }
     58 
     59 void add(ll &a,ll b)
     60 {
     61     a+=b;
     62     if(a>=MOD) a-=MOD;
     63     if(a<0) a+=MOD;
     64 }
     65 
     66 int main()
     67 {
     68     int n=read(),m=read();
     69     if(n==1&&m==1)
     70     {
     71         printf("1
    ");
     72         return 0;
     73     }
     74     rep(i,1,n)
     75     {
     76         scanf("%s",ch+1);
     77         rep(j,1,m)
     78          if(ch[j]=='R') b[i][j]=1;
     79     }
     80     rep(i,1,n)
     81      rep(j,1,m) b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+b[i][j];
     82     dp[1][1][0]=dp[1][1][1]=1;
     83     s[1][1][0]=s[1][1][1]=1;
     84     rep(len,3,n+m)
     85     {
     86         rep(i,1,len-1)
     87         {
     88             int j=len-i;
     89             if(i>n||j>m) continue;
     90             int l=1,r=j-1,last=j;
     91             while(l<=r)
     92             {
     93                 int mid=(l+r)>>1;
     94                 if(calcb(i,mid+1,i,m)<=m-j){last=mid; r=mid-1;}
     95                  else l=mid+1;
     96             }
     97             if(last<j) add(dp[i][j][0],calc(i,last,i,j-1,1));
     98             add(s[i][j][0],s[i-1][j][0]);
     99             add(s[i][j][0],s[i][j-1][0]);
    100             add(s[i][j][0],-s[i-1][j-1][0]);
    101             add(s[i][j][0],dp[i][j][0]);
    102 
    103             l=1,r=i-1,last=i;
    104             while(l<=r)
    105             {
    106                 int mid=(l+r)>>1;
    107                 if(calcb(mid+1,j,n,j)<=n-i){last=mid; r=mid-1;}
    108                  else l=mid+1;
    109             }
    110             if(last<i) add(dp[i][j][1],calc(last,j,i-1,j,0));
    111             add(s[i][j][1],s[i-1][j][1]);
    112             add(s[i][j][1],s[i][j-1][1]);
    113             add(s[i][j][1],-s[i-1][j-1][1]);
    114             add(s[i][j][1],dp[i][j][1]);
    115         }
    116 
    117     }
    118     ll ans=(dp[n][m][0]+dp[n][m][1])%MOD;
    119     printf("%I64d
    ",ans);
    120     return 0;
    121 }
  • 相关阅读:
    NVIC
    ONE WIRE
    对话框
    STM32_USART
    [Java]eclipse的使用
    [转] Android资源管理框架(Asset Manager)简要介绍和学习计划
    [其他]网站收录
    [Java]Java简介
    [网络技术]网关 路由器 OSI
    [安卓]安卓模拟器(Android Emulator)
  • 原文地址:https://www.cnblogs.com/myx12345/p/11749247.html
Copyright © 2011-2022 走看看