uva11552

本文通过动态规划的方法解决了一个求解最小块数的问题,重点在于理解状态转移方程及关键状态量的选择。

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

做过难的dp再做这种,就能很清晰的发现状态转移过程中关键的状态量

就是第i组结束后末尾的字母

dp[i][j]表示前i组,以j结尾的最少块数

dp[i][j] 转移时要转移到全部的dp[i-1][k] 分成k等于j和k不等于j分别考虑

难得1A,水题。。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
const int INF = 111111111;
using namespace std;
 
int main()
 {
 	int t;
 	scanf("%d",&t);
 	while(t--){
 		char s[1005];
 		int have[1005][27];
 		int num[1005];
		int dp[1005][27];
		int k,l,part;
 		memset(have,0,sizeof(have));
 		memset(num,0,sizeof(num));
 		memset(dp,0,sizeof(dp));
		scanf("%d",&k);
		scanf("%s",s);
 		l = strlen(s);
 		part = l / k;
 		for(int i = 1; i <= part; i++){
 			int start = (i - 1)*k;
			for(int j = 0; j < k; j++){
			    if (have[i][s[start + j] - 'a'] != 1)
			        num[i]++;
				have[i][s[start + j] - 'a'] = 1;
	        }
	        //printf("%d\n",num[i]);
	    }
	    for(int j = 0; j <= 25; j++)
	       dp[1][j] = have[1][j]?num[1] : INF;
	    for(int i = 2; i <= part; i++)
		for(int j = 0; j <= 25; j++){
			if (!have[i][j]){
				dp[i][j] = INF;
				continue;
			}
			dp[i][j] = INF;
			for(int q = 0; q <= 25; q++){
				if (q == j){
					if (num[i] == 1) dp[i][j] = min(dp[i][j],dp[i - 1][q]);
					else dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i]);
				}
				else{
					if (have[i][q]) dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i] - 1);
					else dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i]);
				}
			}
		}
		int ans = INF;
		for(int j = 0; j <= 25; j++)
		   ans = min(ans,dp[part][j]);
		printf("%d\n",ans);
	 }
	 return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值