算法难度:普及
思维难度:提高
调码难度:普及
综合评价:较难
动态规划+常数级优化
状态:dp[i][j][k]表示从起点做i次一号操作、j次二号操作、k次三号操作不同的路径(顺序不同但是每种操作总次数相同的路径算不同路径)总数。
初值:dp[0][0][0]为1,啥操作都不做自然只有一种情况。
转移:若做完相应相应操作之后是障碍物则该dp值为0,否则为f[i-1][j][k]+f[i][j-1][k]+f[i][j][k-1],当然,如果i-1、j-1或者k-1小于0就不能加上这一项。
其中,对于是否是障碍物的判断,我们应当用map操作,可是由于常数太大可能会TLE,所以我们在做的时候注意节省常数。
领情参见我录的题解:题解:ABC265E-Wrap_哔哩哔哩_bilibili。
Submission #42746055 - AtCoder Beginner Contest 265
#include
#define N 330
using namespace std;
map,bool>mp={};
int dp[N][N][N]={},a=0,b=0,c=0,d=0,e=0,f=0,m=0,n=0,s=0;
int main(){
scanf("%d%d%d%d%d%d%d%d",&n,&m,&a,&b,&c,&d,&e,&f);
for(int i=1;i<=m;i++){
int x=0,y=0;
scanf("%d%d",&x,&y);
mp[{x,y}]=true;
//记录xy是障碍物
}
for(int i=0;i<=n;i++){
int x=n-i;
//卡常数,这样就不用在下面的循环里每次都判断i+j<=n
for(int j=0;j<=x;j++){
int y=n-i-j;
//与上一个卡常数同理
for(int k=0;k<=y;k++){
if(i==0&&j==0&&k==0){
dp[i][j][k]=1;
//初始值特判
}else{
if(mp[{i*a+j*c+k*e,i*b+j*d+k*f}]==true){
dp[i][j][k]=0;
//障碍物
}else{
if(i!=0){
dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k])%998244353;
}
if(j!=0){
dp[i][j][k]=(dp[i][j][k]+dp[i][j-1][k])%998244353;
}
if(k!=0){
dp[i][j][k]=(dp[i][j][k]+dp[i][j][k-1])%998244353;
}
//三个判断防止调用dp的负数项
}
}
if(i+j+k==n){
s=(s+dp[i][j][k])%998244353;
//如果总共做了n次就更新ans
}
}
}
}
printf("%d\n",s);
return 0;
}
判断边界+开longlong