标签:题意 处理 class std 字符 状态 ring div out
题意:给出p串字符(每串都是20个字母) 给出k ,k表示总共可以分成几部分;
给出词典,这个词典最多包含6个单词,
求如何分,能够得到最多单词;
注:每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用
思路:很明显,这道题应该用dp解法;
首先,我们先将p串字符连成一串
我们需要处理两部分;
第一部分:预处理:我们先预处理出每一个区间范围内的单词个数;
第二部分:dp【i】【j】表示前i个字符分成k块
然后便是dp的代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int m; 4 string s,dic[10],ch; 5 int num[205][205],dp[205][45]; 6 bool judge(int l,int r) 7 { 8 string ss=s.substr(l,r-l+1);//取出l到r的字符串 9 for(int i=1;i<=m;i++) 10 if(ss.find(dic[i])==0) 11 return true;//find返回的是第一个下标 12 return false; 13 } 14 int main() 15 { 16 ios::sync_with_stdio(false); 17 int p,k; 18 cin>>p>>k; 19 s+=‘\0‘;//为了s的下标从1开始 20 for(int i=1;i<=p;i++){ 21 cin>>ch; 22 cout<<ch<<endl; 23 s+=ch; 24 cout<<s<<endl; 25 } 26 cin>>m; 27 for(int i=1;i<=m;i++) 28 cin>>dic[i]; 29 int len=s.length()-1; 30 for(int i=len;i>=1;i--)//预处理单词数,i为右端点,j为左端点 31 { 32 for(int j=i;j>=1;j--) 33 { 34 num[j][i]=num[j+1][i]; 35 if(judge(j,i))num[j][i]++; 36 } 37 } 38 dp[0][0]=0; 39 for(int i=1;i<=len;i++)//边界状态,到i只分成一块即1-i的单词数 40 dp[i][1]=num[1][i]; 41 for(int i=1;i<=len;i++)//枚举右端点,左端点都是max(1,分的段数) 42 for(int j=1;j<=k&&j<=i;j++)//枚举分成了几段 43 for(int l=j;l<i;l++)//枚举左端点与右端点之间的点 44 dp[i][j]=max(dp[i][j],dp[l][j-1]+num[l+1][i]); 45 printf("%d\n",dp[len][k]); 46 return 0; 47 }
转载自:https://blog.csdn.net/qq_40942372/article/details/86699259
标签:题意 处理 class std 字符 状态 ring div out
原文地址:https://www.cnblogs.com/pangbi/p/12493702.html