UVa11552 Fewest Flops
? 解题记录 ? ? UVa ? ? 动态规划 ?    2017-09-14 23:35:23    385    0    0

 

这道题的DP其实可以换一个角度出发思考,因为我们可以随意调整一个块,所以每一个块有字母的种类个数肯定是该块的最优块数。接下来我们只需要确定它们的排布就可以了。我们这样建立状态。dp[i][j]表示第i个块的第一个字母为j时的最少联通个数,这样我们就可以通过dp[i - 1][0~25]推出dp[i][0 ~25]了。

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e3 + 5;
int dp[maxn][26];
bool idx[maxn][26];
int num[maxn];
char s[maxn];

int main() {
	int t, k; scanf("%d", &t);
	while(t--) {
		scanf("%d", &k);
		scanf("%s", s);
		memset(dp, 0x3f, sizeof(dp));
		int len = strlen(s);
		for(register int i = 0; i < len; ++i) 
			num[i / k] += !(idx[i / k][s[i] - 'a']), idx[i / k][s[i] - 'a'] = 1;
		for(register int i = 0; i < 26; ++i) 
			if(idx[0][i]) dp[0][i] = num[0];
		for(register int i = 1; i < len / k; ++i) 
			for(register int j = 0; j < 26; ++j) {
				if(dp[i - 1][j])
					for(register int k = 0; k < 26; ++k)
						if(idx[i][k] && (k != j || num[i - 1] == 1))
							dp[i][k] = min(dp[i - 1][j] + num[i] - (idx[i - 1][k] != 0), dp[i][k]);
			}
		int mn = 0x3f3f3f3f;
		for(register int i = 0; i < 26; ++i)
			if(dp[len / k - 1][i])
				mn = min(dp[len / k - 1][i], mn);
		printf("%d\n", mn);
		memset(idx, 0, sizeof(idx));
		memset(num, 0, sizeof(num));
	}
	return 0;
} 

 

上一篇: SCU3075 回文子串

下一篇: UVa 11426 GCD Extreme(II)

385 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航