Uva 11552 Fewest Flops (三维动态规划)

本文介绍了一种基于字符串的分组算法实现,通过动态规划的方法来寻找最优的字符串分组方式,使得每个分组内的字符串能够尽可能地进行组合,减少整体的分组数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dp[l][i][j] 表示第l个分组以第i个字母组开头以第j个字母组结尾时候最小划分的块数

n=strlen(S)/k

dp[l][i][j] 的值分两种情况:

1.头i在第l-1组中在位置h找到了,说明头尾可以相接,那么遍历l-1组中以h结尾的所有值,求得最小值temp:

dp[l][i][j]=temp+strlen(ss[l])-1;

2.没找到,那么遍历l-1组中的所有值,求得最小值temp:

if(dp[l][i][j]>temp+strlen(ss[l]))dp[l][i][j]=temp+strlen(ss[l]);

最后遍历dp[n-1][i][j]求得最小值即可。

此题千万要仔细,太麻烦了。

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int k,dp[1005][30][30];
char ss[1005][1005],s[1005];
void juhe(int h,int i,int j) //对【i,j)这个块去重
{	int bz[27],l=0; memset(bz,0,sizeof(bz));
	for(;i<j;i++)
		if(bz[s[i]-'a']==0) {ss[h][l++]=s[i];bz[s[i]-'a']=1;}
	ss[h][l]=0;
	//cout<<ss[h]<<" "<<strlen(ss[h])<<endl; 
}
int search_i(int l,int i) //在ss[l-1]中查找ss[l][i] 
{
	for(int j=0;j<strlen(ss[l-1]);j++)
		if(ss[l][i]==ss[l-1][j]) return j;
	return -1;
}
int main(int argc, char *argv[])
{
	int i,j,l,t,n,ans;
	cin>>t;
	while(t--)
	{
		cin>>k>>s; n=strlen(s)/k;
		for(i=0;i<n;i++)
		{
			juhe(i,i*k,(i+1)*k);
		}
		for(l=0;l<n;l++)
		{	for(i=0;i<strlen(ss[l]);i++)
				{
					for(j=0;j<strlen(ss[l]);j++)
					{   
						if(i!=j||(strlen(ss[l])==1)) //头和尾是不能相同的,除非长度为1 
						{
							if(l==0) dp[l][i][j]=strlen(ss[l]); 
							else //两种情况,取小的 
							{   int h=search_i(l,i),temp;
								dp[l][i][j]=10000;
								if(h>=0)//找到匹配,遍历第l-1组中以h结尾的值,得到min 
								{   temp=10000;
									for(int g=0;g<strlen(ss[l-1]);g++)
										if(dp[l-1][g][h]<temp) temp=dp[l-1][g][h];
									dp[l][i][j]=temp+strlen(ss[l])-1;
								}
							   //没有匹配的,遍历第l-1组中所有的值,得到min 
									temp=10000;
									for(int p=0;p<strlen(ss[l-1]);p++)
									for(int q=0;q<strlen(ss[l-1]);q++)
										if(dp[l-1][p][q]<temp) temp=dp[l-1][p][q];
								if(dp[l][i][j]>temp+strlen(ss[l])) dp[l][i][j]=temp+strlen(ss[l]);	
							}
						}
						else dp[l][i][j]=10000; 
					}
				}	
		}
		for(ans=10000,i=0;i<strlen(ss[n-1]);i++)
		for(j=0;j<strlen(ss[n-1]);j++)
			if(dp[n-1][i][j]<ans) ans=dp[n-1][i][j];
		cout<<ans<<endl;
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值