专栏文章
题解:CF118D Caesar's Legions
CF118D题解参与者 9已保存评论 15
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 15 条
- 当前快照
- 1 份
- 快照标识符
- @miqc06gu
- 此快照首次捕获于
- 2025/12/04 02:19 3 个月前
- 此快照最后确认于
- 2025/12/04 02:19 3 个月前
Solution:
很显然,由数据得这种指数级别的暴搜会超时。
我们思考:上面的做法效率低下,是因为同一个状态会被访问多次。
如果我们每查询完一个状态后将该状态的信息存储下来,再次需要访问这个状态就可以直接使用之前计算得到的信息,从而避免重复计算。这充分利用了动态规划中很多问题具有大量重叠子问题的特点,属于用空间换时间的「记忆化」思想。
我们用
m[x][y][tot1][tot2] 表示在还剩 个步兵和 个骑兵且已有 或 个骑兵或步兵连续排列情况下的方案数。奉上AC代码:
CPP#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e8;
int n1,n2,k1,k2,m[101][101][11][11]; //记忆化数组
int read() //快读
{
int x=0,a=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') a=-1;
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-'0';
return x*a;
}
int dfs(int x,int y,int tot1,int tot2) //tot1,tot2分别表示已经选取了连续的几个步兵和骑兵,
//x,y表示还有几个骑兵和步兵未选
{
int ans=0;
if(x==0&&y==0) //方案成立,总数+1
{
ans=1;return ans;
}
if((x==0&&tot2>=k2)||(y==0&&tot1>=k1)) return 0;
if(m[x][y][tot1][tot2]!=-1) return m[x][y][tot1][tot2]; //如果记录过直接返回
if(x>0&&tot1<k1)
{
ans+=dfs(x-1,y,tot1+1,0);
ans%=mod;
}
if(y>0&&tot2<k2)
{
ans+=dfs(x,y-1,0,tot2+1);
ans%=mod;
}
m[x][y][tot1][tot2]=ans%mod; //记录这种情况
return ans%mod;
}
signed main()
{
// freopen("a.in","r",stdin);
n1=read();n2=read();
k1=read();k2=read();
memset(m,-1,sizeof m); //建议赋一个比0小的初值,因为答案的情况可能为任意非负整数
cout<<dfs(n1,n2,0,0)%mod;
return 0;
}
相关推荐
评论
共 15 条评论,欢迎与作者交流。
正在加载评论...