P4170 [CQOI2007] 涂色

Problem: P4170 [CQOI2007] 涂色

思路

对于这道题,我们采用动态规划的策略来解决。问题的关键在于找到如何将大的子问题分解为更小的子问题,并且定义状态转移方程。具体来说,我们可以定义dp[i][j]表示将第i到第j个位置涂色所需要的最小次数。如果s[i]==s[j],那么dp[i][j]可以等于dp[i][j-1],因为最后一步涂j位置的颜色时,可以直接覆盖之前在j-1位置的颜色;否则,我们需要考虑所有可能的分割方式,即在i和j之间找到一个k,使得dp[i][j]等于dp[i][k]+dp[k+1][j]的最小值。

解题方法

我们首先初始化dp数组,对于所有的dp[i][i]设为1,表示单个位置涂色需要一次操作;对于相邻的两个位置,如果颜色相同则dp[i][i+1]=1,否则dp[i][i+1]=2。接下来,我们从长度为3的子串开始,逐渐增加子串的长度,更新dp数组中的值。

复杂度

时间复杂度:

O ( n 3 ) O(n 3 ) O(n3),其中n是字符串的长度。这是因为我们对每一个长度从3到n的子串都进行了遍历和更新,而更新一个子串的时间复杂度为O(n),所以总的时间复杂度为 O ( n 3 ) O(n^3) O(n3).

空间复杂度:

O ( n 2 ) O(n 2 ) O(n2),我们使用了n*n大小的dp数组,空间复杂度为 O ( n 2 ) O(n^2) O(n2).

Code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class Main {
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	public static void main(String[] args) throws IOException {
		String str = in.readLine();
		out.println(strangePrinter(str));
		out.flush();
		
	}
	public static int strangePrinter(String str) {
		int n = str.length();
		char[] s = str.toCharArray();
		int[][] dp = new int[n][n];
		dp[n - 1][n - 1] = 1;
		for(int i = 0; i < n - 1; i++) {
			dp[i][i] = 1;
			dp[i][i + 1] = s[i] == s[i + 1] ? 1 : 2;
		}
		for(int l = n - 3; l >= 0; l --) {
			for(int r = l + 2; r < n; r++) {
				if(s[l] == s[r]) {
					dp[l][r] = dp[l][r - 1];
				} else {
					int ans = Integer.MAX_VALUE;
					for(int m = l; m < r; m++) {
						ans = Math.min(ans, dp[l][m] + dp[m + 1][r]);
					}
					dp[l][r] = ans;
				}
			}
		}
		return dp[0][n - 1];
	}

}

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱跑步的程序员~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值