Educational Codeforces Round 115 (Rated for Div. 2) E dp
题目链接
https://codeforces.com/problemset/problem/1598/E
题意
有两种形态的楼梯是合法的,其中每种楼梯的每个经过的格子都要是非锁定的,还会问你q个问题,每次改变这个格子的锁定状态,问你当前情况下有多少种楼梯的合法情况
我的思路
问题分为两部分:求解初始总方案数,和每次修改带来的总方案数的变化量。
令dp1[i][j] dp2[i][j] 分别表示从左边转移到当前一格,和从上面转移到当前一格的合法方案数,据此易求出初始状态的方案
分析楼梯的性质知,每次改变只会让一定区域内的合法方案数改变。具体见代码
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,q;
bool locked[1005][1005];
ll dp1[1005][1005],dp2[1005][1005];
int x,y;
ll tot=0;
int main(){
cin>>n>>m>>q;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp1[i][j]=1+dp2[i][j-1];
dp2[i][j]=1+dp1[i-1][j];
tot+=dp1[i][j]+dp2[i][j]-1;
}
}
// cout<<tot<<endl;
while(q--){
scanf("%d%d",&x,&y);
if(locked[x][y]==0){
locked[x][y]=1;
for(int i=x,j=y+1,k=1;i<=n&&j<=m;k++){
if(locked[i][j]) break;
if(k%2){
dp1[i][j]-=dp2[x][y];
tot-=dp2[x][y];
i++;
}
else{
dp2[i][j]-=dp2[x][y];
tot-=dp2[x][y];
j++;
}
}
for(int i=x+1,j=y,k=1;i<=n&&j<=m;k++){
if(locked[i][j]) break;
if(k%2){
dp2[i][j]-=dp1[x][y];
tot-=dp1[x][y];
j++;
}
else{
dp1[i][j]-=dp1[x][y];
tot-=dp1[x][y];
i++;
}
}
tot-=(dp1[x][y]+dp2[x][y]-1);
dp1[x][y]=0;
dp2[x][y]=0;
}
else{
locked[x][y]=0;
dp1[x][y]=1+dp2[x][y-1];
dp2[x][y]=1+dp1[x-1][y];
tot+=dp1[x][y]+dp2[x][y]-1;
for(int i=x,j=y+1,k=1;i<=n&&j<=m;k++){
if(locked[i][j]) break;
if(k%2){
dp1[i][j]+=dp2[x][y];
tot+=dp2[x][y];
i++;
}
else{
dp2[i][j]+=dp2[x][y];
tot+=dp2[x][y];
j++;
}
}
for(int i=x+1,j=y,k=1;i<=n&&j<=m;k++){
if(locked[i][j]) break;
if(k%2){
dp2[i][j]+=dp1[x][y];
tot+=dp1[x][y];
j++;
}
else{
dp1[i][j]+=dp1[x][y];
tot+=dp1[x][y];
i++;
}
}
}
printf("%lld\n",tot);
}
return 0;
}

浙公网安备 33010602011771号