2.8
2.8
[P1004 NOIP 2000 提高组] 方格取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 这道题一开始是想用\(dp[i][j]\)来代表走到i,j后所得到的最大值,根据转移方程\(dp[i][j] = max(dp[i][j - 1],dp[i - 1][j]) + a[i][j]\)然后通过记录方向的方法,回溯回去把路径上的值赋值为0。
- 但是结果是有问题的,这种方法本质上感觉是一种贪心,我们陷入了局部最优,我们只是保证了每一次路径是最大值,并没有保证两个路径之和是最大值。
- 改变之后决定更换dp状态,\(dp[i][j][k][t]\),表示走到第一次走到i,j,和第二次走到k,t得到的最大值。ok那么转移方程跟着更新即可,\(dp[i][j][k][t] = max(dp[i][j - 1][k][t - 1],dp[i - 1][j][k - 1][t], dp[i][j - 1][k - 1][t], dp[i - 1][j][k][t - 1]) + a[i][j] + a[k][t]\),当然当两点重合时,要减去一个,因为我们同一个点加了两次。
import java.io.*;
import java.util.*;
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 = 10;
static long[][] g = new long[N][N];
static long[][][][] dp = new long[N][N][N][N];//dp[i][j] 走到i,j时所得到的最大值
static int[][] fangXiang = new int[N][N];
// 1为you,2为xia,3为youxia
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;
}
@Override
public void run() {
try {
n = nextInt();
int x = nextInt(), y = nextInt();long val = nextInt();
while(x != 0 && y != 0 && val != 0) {
g[x][y] = val;
x = nextInt(); y = nextInt(); val = nextInt();
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
for (int z = 1; z <= n; z++) {
dp[i][j][k][z] = Math.max(Math.max(dp[i - 1][j][k - 1][z], dp[i][j - 1][k - 1][z]),
Math.max(dp[i][j - 1][k][z - 1], dp[i - 1][j][k][z - 1])) + g[i][j] + g[k][z];
if (i == k && j == z) {
dp[i][j][k][z] -= g[i][j];
}
}
}
}
}
cout.println(dp[n][n][n][n]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
[P1091 NOIP 2004 提高组] 合唱队形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 很简单,其实就是求最大上升子序列,我们正着求一次,反着求一次,再枚举每一个点(记得减1),只要两者和最大,那么剔除的人就最少
import java.io.*;
import java.util.*;
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 = 110;
static long[] t = new long[N];
static long[] dpl_r = new long[N];
static long[] dpr_l = new long[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;
}
@Override
public void run() {
try {
n = nextInt();
for (int i = 1; i <= n; i++) t[i] = nextInt();
Arrays.fill(dpl_r, 1);Arrays.fill(dpr_l, 1);
for (int i = 1; i <= n; i++) {
for (int j = i - 1; j >= 1; j--) {
if (t[j] < t[i]) {
dpl_r[i] = Math.max(dpl_r[j] + 1, dpl_r[i]);
}
}
}
for (int i = n; i >= 1; i--) {
for (int j = i + 1; j <= n; j++) {
if (t[j] < t[i]) {
dpr_l[i] = Math.max(dpr_l[j] + 1, dpr_l[i]);
}
}
}
long cnt = 0;
for (int i = 1; i <= n; i++) {
cnt = Math.max(dpl_r[i] + dpr_l[i] - 1, cnt);
}
long ans = n - cnt;
cout.println(ans);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
[P2679 NOIP 2015 提高组] 子串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 本题确实对我来说有点太难了,选用的这个题解的方法,没看得好懂,照着其转移方程码的代码,,,,感兴趣的去看原作者吧。。。
题解 P2679 【子串】 - 洛谷专栏 (luogu.com.cn)
import java.io.*;
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 = (int) (1e3 + 10);
static final int M = 210;
static final int mod = 1000000007;
static int[][][][] dp = new int[2][M][M][2];//dp[i,j,k,z] 表示以a串i位置结束时,b串j位置结束,所配对子串k,z选或不选
static int n, m, k;
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();m = nextInt();k = nextInt();
String s1 = next(); String s2 = next();
int val = 1;
dp[0][0][0][0] = 1;dp[1][0][0][0] = 1;
for(int i = 1; i <= n; i++, val ^= 1) {
for (int j = 1; j <= m; j++) {
for(int t = 1; t <= k; t++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[val][j][t][0] = (dp[val^1][j][t][1] + dp[val^1][j][t][0]) % mod;
dp[val][j][t][1] = (((dp[val^1][j - 1][t - 1][1] + dp[val^1][j - 1][t - 1][0] ) % mod)
+ dp[val^1][j - 1][t][1]) % mod;
} else {
dp[val][j][t][0] = (dp[val^1][j][t][1] + dp[val^1][j][t][0]) % mod;
dp[val][j][t][1] = 0;
}
}
}
}
cout.println((dp[n&1][m][k][1] + dp[n&1][m][k][0]) % mod);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
浙公网安备 33010602011771号