uva11552题解(dp)

题意是将一字符串划分为若干组,组内可以重排位置,求最后最小包含的块数(即相同字母组成的连续字符串的个数)


这题是序列划分模型,有点类似于 商人那道题,主要是状态的设计,另dp(i,j)为第i个序列首字为j所能划分最小组数,可以很容易得到状态方程 ps额一开始脑洞开得有点大,各种边界没考虑清楚,需要注意的是,假如第i个序列以j开头,并不一定第i-1个序列以j结尾答案就最小,因为我们不能以局部来代替整体,这也是一开始一直wa的原因(泪目)

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include 
#include
#include 
#include
using namespace std;  
#define LL long long  
const int maxn=1005;
const int INF=1000000000;


int d[maxn][30];
set str[maxn];


int main(){
	int t;
	scanf("%d",&t); 
	while(t--){
		int k;scanf("%d",&k);
		string s;cin>>s;
		
		int len=s.length();
		int grp=len/k;
		for(int i=1;i<=grp;i++) str[i].clear();
		
		for(int i=1;i<=grp;i++){
			for(int j=0;j::iterator j=str[i].begin();j!=str[i].end();j++){
				if(i==1){d[i][*j]=sizei;continue;}
				d[i][*j]=INF;
				if(str[i-1].count(*j)){
					if(str[i-1].size()!=1)
						for(set::iterator k=str[i-1].begin();k!=str[i-1].end();k++){
							if(*k!=*j) d[i][*j]=min(d[i][*j],d[i-1][*k]+sizei-1);
							else d[i][*j]=min(d[i][*j],d[i-1][*k]+sizei);
						}
					else d[i][*j]=d[i-1][*j]+sizei-1;
				}
				else{
					for(set::iterator k=str[i-1].begin();k!=str[i-1].end();k++){
						d[i][*j]=min(d[i][*j],d[i-1][*k]+sizei);
					}
				}
			}
		}
		
		int ans=INF;
		for(set::iterator i=str[grp].begin();i!=str[grp].end();i++)
			ans=min(ans,d[grp][*i]);	
		printf("%d\n",ans);

	}
	return 0;
}  

你可能感兴趣的:(程序设计竞赛)