DP
题目大意
给出一个字符串 s s s,要求将 s s s,分成连续的 k k k 段并满足每段长度在区间 [ l , r ] [l,r] [l,r] 之内,也就是每段长度大于等于 l l l 且小于等于 r r r
解题思路
设
f
[
i
]
[
j
]
f[i][j]
f[i][j] 为长度为
i
i
i 的字符串分成
j
j
j 段的方案是否可行
vector 数组
g
[
i
]
[
j
]
g[i][j]
g[i][j] 储存对应的
f
[
i
]
[
j
]
f[i][j]
f[i][j] 方案中所有的字符串分界点
很简单的 O ( n 3 ) O(n^3) O(n3) 转移
f[0][0]=1;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j) // 最多只能分成 i 段,因为只有 i 个字符
{
for(int k=i-r;k<=i-l;++k)
{
if(!f[k][j-1])continue;
f[i][j]=1;
g[i][j]=g[k][j-1];
g[i][j].push_back(i);
break;
}
}
}
完整代码
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int Maxn=220,inf=0x3f3f3f3f;
char str[Maxn];
bool f[Maxn][Maxn];
vector <int> g[Maxn][Maxn];
int n,m,l,r;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
int main()
{
// freopen("in.txt","r",stdin);
m=read(),l=read(),r=read();
scanf("%s",str+1);
n=strlen(str+1);
f[0][0]=1;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
for(int k=i-r;k<=i-l;++k)
{
if(!f[k][j-1])continue;
f[i][j]=1;
g[i][j]=g[k][j-1];
g[i][j].push_back(i);
break;
}
}
}
if(!f[n][m])
{
puts("No solution");
return 0;
}
int tmp=0;
for(int i=1;i<=n;++i)
{
putchar(str[i]);
if(i==g[n][m][tmp])
{
putchar('\n');
++tmp;
}
}
return 0;
}