2.15
CF607B Zuma - 洛谷 (luogu.com.cn)
- \(dp[i][j]\)表示在这个\((i,j)\)区间中所使用的最短时间。
- 考虑转移方程,因为是回文字符串,所以当\(arr[left] != arr[right]\)时,有\(dp[left][right] = dp[left + 1][right - 1]\),因为用同一步可以同时消除他们,当\(arr[left] == arr[right]\)时,有\(dp[left][right]=min(dp[left][k] + dp[k+1][right])\)
- 考虑递归顺序,由于我们是用小区间推导大区间,所以是从小到大
- 考虑初始状态,先考虑长度为1和2时,则需要初始化一下长度为1,2的区间,\(dp[i][i]=1,dp[i][i+1]=(1,2)\),于是就可以直接做了
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
public class Main implements Runnable {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n;
static final int N = (int) (5e2 + 10);
static int[] arr = new int[N];
static int[][] dp = new int[N][N];
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int) cin.nval;
}
public static String next() throws IOException {
cin.nextToken();
return cin.sval;
}
@Override
public void run() {
try {
n = nextInt();
for (int i = 1; i <=n; i++) {
Arrays.fill(dp[i], 0x3f3f3f3f);
}
for (int i = 1; i <= n; i++) {
arr[i] = nextInt();
dp[i][i] = 1;
}
for (int left = 1; left + 1 <= n; left++) {
int right = left + 1;
if (arr[left] != arr[right]) {
dp[left][right] = 2;
} else {
dp[left][right] = 1;
}
}
for (int len = 3; len <= n; len++) {
for (int left = 1; left + len - 1 <= n; left++) {
int right = left + len - 1;
if (arr[left] == arr[right]) {
dp[left][right] = dp[left + 1][right - 1];
}
for (int k = left; k < right; k++) {
dp[left][right] = Math.min(dp[left][right], dp[left][k] + dp[k + 1][right]);
}
}
}
cout.println(dp[1][n]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
[P4170 CQOI2007] 涂色 - 洛谷 (luogu.com.cn)
- \(dp[i][j]\)表示区间(i,j)的最少涂色次数
- 转移方程其实和上题有一点相似
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
public class Main implements Runnable {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static final int N = 55;
static int[] arr = new int[N];
static int[][] dp = new int[N][N];//dp[i,j]表示i,j的最少涂色次数
//dp[i,i] 1次 dp[i,i+1] 2次
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int) cin.nval;
}
public static String next() throws IOException {
cin.nextToken();
return cin.sval;
}
@Override
public void run() {
try {
String s = next();
for (int i = 1; i <= s.length(); i++) {
Arrays.fill(dp[i], 0x3f3f3f3f);
}
for (int i = 1; i <= s.length(); i++) {
arr[i] = s.charAt(i - 1) - 'A';
dp[i][i] = 1;
}
for (int i = 1; i < s.length(); i++) {
if (arr[i] != arr[i + 1]) {
dp[i][i + 1] = 2;
} else {
dp[i][i + 1] = 1;
}
}
for (int len = 3; len <= s.length(); len++) {
for (int left = 1; left + len - 1 <= s.length(); left++) {
int right = left + len - 1;
if (arr[left] == arr[right]) {
dp[left][right] = Math.min(dp[left][right - 1], dp[left + 1][right]);
}
for (int k = left; k < right; k++) {
dp[left][right] = Math.min(dp[left][right], dp[left][k] + dp[k + 1][right]);
}
}
}
cout.println(dp[1][s.length()]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
[P4290 HAOI2008] 玩具取名 - 洛谷 (luogu.com.cn)
- \(can[i][j][k]\)表示i是否可以用j和k两个字母(用数字替代)来替代,\(dp[i][j][k]\)表示k是否可以由(i, j)区间转移得到,简单说就是i,j区间转移为k这个字母
- 转移方程由当\(dp[left][k][x] = true,dp[k+1][right][y]=true,can[z][x][y] = true\)时,\(dp[left][right][z] = true\),所以就时要遍历x,y,z,k,left,right,len即可
- 考虑迭代方向,肯定是由小到大
- 那么考虑初始化,就是\(dp[i][i][change(i)]\)可以想到就是i这个字母可以转移为他自身,can的初始化就不用详细说明了
- 照着思路把代码写出来就行了
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
public class Main implements Runnable {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static final int N = 215;
static boolean[][][] can = new boolean[N][N][N];
static boolean[][][] dp = new boolean[N][N][N];
public static int change(char x) {
if (x == 'W') return 1;
if (x == 'I') return 2;
if (x == 'N') return 3;
return 4;
}
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int) cin.nval;
}
public static String next() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void init(int x, int cnt) throws IOException {
for (int i = 1; i <= x; i++) {
String s = next();
can[cnt][change(s.charAt(0))][change(s.charAt(1))] = true;
}
}
@Override
public void run() {
try {
int x1 = nextInt();int y1 = nextInt();int z1 = nextInt();int g = nextInt();
init(x1, 1);init(y1,2);init(z1, 3);init(g, 4);
String s = next();
for (int i = 1; i <= s.length(); i++) {
dp[i][i][change(s.charAt(i - 1))] = true;
}
for (int len = 2; len <= s.length(); len++) {
for (int left = 1; left + len - 1 <= s.length(); left++) {
int right = left + len - 1;
for (int k = left; k < right; k++) {
for (int x = 1; x <= 4; x++) {
for (int y = 1; y <= 4; y++) {
for (int z = 1; z <= 4; z++) {
if (dp[left][k][x] && dp[k + 1][right][y] && can[z][x][y]) {
dp[left][right][z] = true;
}
}
}
}
}
}
}
boolean flag = false;
if (dp[1][s.length()][1]) {
flag = true;
cout.print('W');
}
if (dp[1][s.length()][2]){
flag = true;
cout.print('I');
}
if (dp[1][s.length()][3]) {
flag = true;
cout.print('N');
}
if (dp[1][s.length()][4]) {
flag = true;
cout.print('G');
}
if (!flag) {
cout.println("The name is wrong!");
}
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
浙公网安备 33010602011771号