uva 1351 - String Compression(dp)

1706 단어
제목 링크: uva 1351 - String Compression
제목 대의: 인접한 m개의 연속 문자열이 s0이면 이 단락을 m(s0)로 표시하고 가장 짧은 몇 개의 문자가 주어진 문자열을 표시할 수 있는지 물어본다.
문제풀이 사고방식: 우선 (1)m는 두 자리 수, 세 자리 수일 수 있음을 주의해야 한다.(2) 좌우 괄호는 각각 문자를 계산한다.(3)s0은 간략화된 문자열을 만들 수 있다. 예를 들어 s0에 k(s1)가 포함되어 있다.
그 다음에 dp[i] [j]는 i에서 j까지의 최소 문자수를 의미하고 i~j 이 문자열이 간화될 수 있는 것을 고려하지 않으면 dp[i] [j] = min [i] [i] [k] + dp[k+1] [j]]수를 표시하고 i~j 이 문자열이 간화될 수 있는 경우 dp[i] [j] [j] ==[j]} 대신 i~j 문자열이 간화될 수 있는 경우도 고려하여 s0의 길이를 매거한 다음에 제목의 요구를 충족하는지 판단하고 요구를 충족하는지를 판단해야 한다. 요구를 충족하는 경우 dp[i] [i] [i] [i] [i] [i] [i] [i] [i] [i] [i] [j] [j] [j] [j] [j] [j] [j] [j] [j])
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;
const int N = 205;
const int INF = 0x3f3f3f3f;

int dp[N][N];
char str[N];

bool judge(int l, int r, int k) {
	if ((r-l+1)%k) return false;

	for (int i = 0; i < k; i++) {
		for (int j = l+i+k; j <= r; j += k) if (str[l+i] != str[j])
			return false;
	}		
	return true;
}

int catnum(int x) {
	int ans = 0;
	while (x) {
		ans++;
		x /= 10;
	}
	return ans;
}

int solve () {

	scanf("%s", str+1);
	int n = strlen(str+1);

	memset(dp, INF, sizeof(dp));
	for (int i = 0; i <= n; i++) dp[i][i] = 1;

	for (int i = n; i; i--) {
		for (int j = i; j <= n; j++) {
			for (int k = i; k < j; k++) 
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);

			int t = j - i + 1;
			for (int k = 1; k < t; k++) if (judge(i, j, k)) {
				dp[i][j] = min(dp[i][j], dp[i][i+k-1] + 2 + catnum(t/k));
			}
		}
	}
	return dp[1][n];
}

int main () {
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		printf("%d
", solve()); } return 0; }

좋은 웹페이지 즐겨찾기