描述:将一段文本分成最少的几段,全是由空格和字母组成的最长可拥有m个字符,否则最多含n个字符。
求最少的段数。
我们假设第一种方案是只存储空格和字母,第二种方案为其他。
DP : dp[i][0] 表示到i这个点且这个点用的是第一种方案的最少的切段。
dp[i][1] 表示。。。。。。。。。。。。第二种方案。。。。。
然后就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<map>
using namespace std;
#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define bug puts("Fuck");
#define LL long long
#define pb push_back
#define mp make_pair
#define nMax 101000
#define eps 1e-8
#define inf 0x7fffffff
char s[nMax];
int n,m;
int l[nMax],dp[nMax][2];
int in(char ch){
return ch==' ' || (ch>='a' && ch<='z') || (ch>='A'&&ch<='Z') ;
}
void sovle(){
l[0]=0;
s[0]='.';
for(int i=1;s[i];i++) if(in(s[i])){
l[i]=l[i-1];
}else l[i]=i;
dp[0][0]=dp[0][1]=0;
int i;
for(i=1;s[i];i++) {
int j=i-n;
if(j<=0) j=0;
dp[i][0] = min(dp[j][0],dp[j][1]) + 1;
if(in(s[i])) {
int j = l[i];
if(i-m > j) j=i-m;
dp[i][1] = min(dp[j][0],dp[j][1]) + 1;
}else dp[i][1] = inf;
// printf("%d %d %d \n",i,dp[i][0],dp[i][1]);
}
int ans = min(dp[i-1][0],dp[i-1][1]);
printf("%d\n",ans);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m)){
gets(s);gets(s+1);
sovle();
}
return 0;
}
