AT_dp_T & UVA1650 & P2467
传送门:
AT_dp_T Permutation
UVA1650 Number String
P2467 地精部落
基本模板:AT_dp_T
题面
给定一个长为
题解
朴素算法
看到 DP 题,首先应该设计状态。
设
然后就可以想状态转移了。
首先,如果将
可以考虑上一位填的数是什么,然后将答案汇总到
对于
对于
最终答案为
时间复杂度
优化1
看到
由于每一个
综上:
时间复杂度
优化2
看到
空间复杂度
举一反三
UVA1650
加了一种可能性,就是字符串中有问号,而这个问号可能代表
所以,问号代表的是
这个就比之前的大于小于好处理多了,由于在枚举
转移就将上一位的所有答案之和单开一个变量储存,然后再把这个变量赋值给所有
综上:
时间复杂度
P2467
给定一个数
做过前两题,那么很容易便可以想出这题的解法,就是大于小于号交替排列,然后再用 AT_dp_T 的 DP 式子即可。
注意大于小于号总共有两种排列方式,可以想到这两种方案得到的答案相同,因此只用求一种的答案,然后将其乘
时间复杂度
代码
AT_dp_T
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3002;
const ll p=1e9+7;
int n;
char a[N];
ll f[2][N];
ll ans;
int main() {
scanf("%d",&n);
cin>>(a+1);
f[1][1]=1;
for(int i=2;i<=n;i++) {
if(a[i-1]=='>') for(int j=i;j;j--) f[i&1][j]=(f[i&1][j+1]+f[(i-1)&1][j])%p;
if(a[i-1]=='<') for(int j=1;j<=i;j++) f[i&1][j]=(f[i&1][j-1]+f[(i-1)&1][j-1])%p;
}
for(int i=1;i<=n;i++) ans=(ans+f[n&1][i])%p;
printf("%lld",ans);
return 0;
}
UVA1650
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll p=1e9+7;
const int N=1002;
int n;
char s[N];
ll f[2][N];
ll ans;
void init() {
memset(f,0,sizeof f);
memset(s,0,sizeof s);
ans=n=0;
return;
}
int main() {
while(cin>>(s+1)) {
n=strlen(s+1)+1;
f[1][1]=1;
for(int i=2;i<=n;i++) {
if(s[i-1]=='I') for(int j=1;j<=i;j++) f[i&1][j]=(f[i&1][j-1]+f[(i-1)&1][j-1])%p;
if(s[i-1]=='D') for(int j=i;j;j--) f[i&1][j]=(f[i&1][j+1]+f[(i-1)&1][j])%p;
if(s[i-1]=='?') {
f[i&1][1]=0ll;
for(int j=1;j<i;j++) f[i&1][1]=(f[i&1][1]+f[(i-1)&1][j])%p;
for(int j=2;j<=i;j++) f[i&1][j]=f[i&1][1];
}
}
for(int i=1;i<=n;i++) ans=(ans+f[n&1][i])%p;
printf("%lld\n",ans);
init();
}
return 0;
}
P2467
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4202;
ll p;
int n;
char a[N];
ll f[2][N];
ll ans;
int main() {
scanf("%d%lld",&n,&p);
for(int i=1;i<n;i++) {
if(i&1) a[i]='>';
else a[i]='<';
}
f[1][1]=1;
for(int i=2;i<=n;i++) {
if(a[i-1]=='>') for(int j=i;j;j--) f[i&1][j]=(f[i&1][j+1]+f[(i-1)&1][j])%p;
if(a[i-1]=='<') for(int j=1;j<=i;j++) f[i&1][j]=(f[i&1][j-1]+f[(i-1)&1][j-1])%p;
}
for(int i=1;i<=n;i++) ans=(ans+f[n&1][i])%p;
printf("%lld",ans*2%p);
return 0;
}
完结撒花!!!!