2.9
2.9
[P1435 IOI 2000] 回文字串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 先说思路,我们这里有样例Ab3bd,反着读是db3bA,我们发现重复的是b3b,不重复的是Ad两个字符,相当于我们只要补全这两个字符为偶数,就可以使他成为回文串。答案就为2。
- ok,那么就把问题转移成了简单的两个子串求最长子序列的问题。
import java.io.*;
import java.util.Scanner;
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 Scanner cin = new Scanner(System.in);
static final int N = (int) (1e3 + 10);
static long[][] dp = new long[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() {
String s1 = cin.next();
String s2 = new StringBuffer(s1).reverse().toString();
for (int i = 1; i <= s1.length(); i++) {
for (int j = 1; j <= s2.length(); j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout.println(s1.length() - dp[s1.length()][s2.length()]);
cout.flush();
}
}
P1854 花店橱窗布置 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 状态数组\(dp[i][j]\)表达的意义为,前i多花要插入前j个花瓶可以得到的最大美学值。
- 由于我们的顺序是定死了的,则我们在枚举花瓶j时,必须要控制其转换方程是由\((1,j-1)\)这个区间转换而来的。
- 那么转移方程为\(dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + color[i][j])\)
- 注意我们这个方程\(dp[i][j]\),表达意思中前j个花瓶(默认第i多花放在花瓶j中)
- 我们只需要枚举\((f, v)\)找到最大的美学值,然后找到是上一行哪一个值迭代出来的就行了
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
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) (1e2 + 10);
static long[][] dp = new long[N][N];
static int f, v;
static int[][] arr = new int[N][N];
static int[][] fangXiang = new int[N][N];
static int[] pp = new int[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 {
f=nextInt();v=nextInt();
for (int i = 1; i <= f; i++) {
for (int j = 1; j <= v; j++) {
arr[i][j] = nextInt();
}
}
for (int i = 1; i <= f; i++) {
Arrays.fill(dp[i], -0x3f3f3f3f);
}
for (int i = 1; i <= f; i++) {
for (int j = 1; j <= v; j++) {
for (int k = 1; k <= j; k++) {
if (dp[i - 1][j - k] + arr[i][j] > dp[i][j]) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k] + arr[i][j]);
fangXiang[i][j] = j - k;
}
}
}
}
int l = 0;
long ans = -0x3f3f3f3f;
int startX = 0, startY = 0;
for (int i = f; i <= v; i++) {
if (dp[f][i] > ans) {
ans = Math.max(ans, dp[f][i]);
startX = f; startY = i;
}
}
cout.println(ans);
pp[++l] = startY;
for (int i = 1; i < f; i++) {
startY = fangXiang[startX][startY];
startX--;
pp[++l] = startY;
}
for (int i = f; i >= 1; i--) {
cout.print(pp[i] + " ");
}
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
P1833 樱花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 首先本题是一个组合背包问题(完全背包+多重背包+01背包)
- 所以我们要先知道这几个背包咋做
- 01背包:每一个物品只能买一次
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Main implements Runnable {
// static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, v;
static final int N = 1010;
static bag[] bags = new bag[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 {
return cin.nextInt();
}
public static String next() throws IOException {
return cin.next();
}
@Override
public void run() {
try {
n = nextInt(); v = nextInt;
for(int i = 1; i <= n; i++) {
bags[i] = new bag();
int val = nextInt();
int weight = nextInt();
bags[i].val = val;bags[i].weight = weight;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= v; j++) {
if(j < bags[i].weight) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - bags[i].weight] + bags[i].val)
}
}
}
cout.println(dp[n][v]);
cout.flush;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class bag {
int val;
int weight;
}
}
- 完全背包:每一个物品可以买很多次
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Main implements Runnable {
// static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, v;
static final int N = 1010;
static bag[] bags = new bag[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 {
return cin.nextInt();
}
public static String next() throws IOException {
return cin.next();
}
@Override
public void run() {
try {
n = nextInt(); v = nextInt();
for(int i = 1; i <= n; i++) {
bags[i] = new bag();
int val = nextInt();
int weight = nextInt();
bags[i].val = val;bags[i].weight = weight;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= v; j++) {
if(j < bags[i].val) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - bags[i].val] + bags[i].weight);
}
}
}
cout.println(dp[n][v]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class bag {
int val;
int weight;
}
}
- 多重背包(每个物品可以取有限次),可以理解成把多重背包拆解成01背包,有三种方法,其一种每个多重背包化解成拆分成单个01背包复杂度为\(O(n*\sum cnt)\),其二运用2进制优化拆分成01背包\(O(n * log (cnt))\),还有优先队列(有点小难)可以优化到\(O(n * m)\)
- 朴素版
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Main implements Runnable {
// static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, v;
static final int M = (int) (1e4 + 10);
static bag[] bags = new bag[M];
static int[] dp = new int[M];
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
return cin.nextInt();
}
public static String next() throws IOException {
return cin.next();
}
@Override
public void run() {
try {
n = nextInt(); v = nextInt();
int num = 0;
for(int i = 1; i <= n; i++) {
int weight = nextInt();
int val = nextInt();
int cnt = nextInt();
for(int j = 1; j <= cnt; j++) {
bags[++num] = new bag();
bags[num].val = val;bags[num].weight = weight;
}
}
//cout.println(num);
for(int i = 1; i <= num; i++) {
for(int j = v; j >= bags[i].weight; j--) {
if(j < bags[i].weight) {
dp[j] = dp[j];
} else {
dp[j] = Math.max(dp[j], dp[j - bags[i].weight] + bags[i].val);
}
}
}
cout.println(dp[v]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class bag {
int val;
int weight;
}
}
- 2进制优化版
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Main implements Runnable {
// static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, v;
static final int M = (int) (2e4 + 10);
static bag[] bags = new bag[M];
static int[] dp = new int[M];
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
return cin.nextInt();
}
public static String next() throws IOException {
return cin.next();
}
@Override
public void run() {
try {
n = nextInt(); v = nextInt();
int num = 0;
for(int i = 1; i <= n; i++) {
int weight = nextInt();
int val = nextInt();
int cnt = nextInt();
int k = 1;
while(k <= cnt) {
bags[++num] = new bag();
bags[num].val = val * k; bags[num].weight = weight * k;
cnt -= k;
k *= 2;
}
if(cnt != 0) {
bags[++num] = new bag();
bags[num].val = val * cnt; bags[num].weight = weight * cnt;
}
}
//cout.println(num);
for(int i = 1; i <= num; i++) {
for(int j = v; j >= bags[i].weight; j--) {
if(j < bags[i].weight) {
dp[j] = dp[j];
} else {
dp[j] = Math.max(dp[j], dp[j - bags[i].weight] + bags[i].val);
}
}
}
cout.println(dp[v]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class bag {
int val;
int weight;
}
}
- ok,所以组合背包其实就是01背包和完全背包的结合体,问题解决
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Main implements Runnable {
// static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, hs, ms, he, me;
static final int N = (int) (1e3 + 10);
static final int M = (int) (1e5 + 10);
static bag[] bags = new bag[M];
static long[] dp = new long[N];
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
return cin.nextInt();
}
public static String next() throws IOException {
return cin.next();
}
@Override
public void run() {
try {
String begin = next(); String end = next();n = nextInt();
String[] split = begin.split(":");
String[] split1 = end.split(":");
hs = Integer.parseInt(split[0]); ms = Integer.parseInt(split[1]);
he = Integer.parseInt(split1[0]); me = Integer.parseInt(split1[1]);
int totalTime = 0;
if (me < ms) {
he--;me += 60;
}
totalTime = (he - hs) * 60 + (me - ms);//容量
int num = 0;
for(int i = 1; i <= n; i++) {
int time = nextInt();int color = nextInt();int p = nextInt();
if (p == 0) {
bags[++num] = new bag();
bags[num].time = time; bags[num].color = color;bags[num].blog = 1;
} else {
int k = 1;
while(k <= p) {
bags[++num] = new bag();
bags[num].time = time * k; bags[num].color = color * k;bags[num].blog = 0;
p -= k;
k *= 2;
}
if (p != 0) {
bags[++num] = new bag();
bags[num].time = time * p; bags[num].color = color * p;bags[num].blog = 0;
}
}
}
for (int i = 1; i <= num; i++) {
if (bags[i].blog == 0) {
for (int j = totalTime; j >= bags[i].time; j--) {
dp[j] = Math.max(dp[j], dp[j - bags[i].time] + bags[i].color);
}
} else {
for (int j = bags[i].time; j <= totalTime; j++) {
dp[j] = Math.max(dp[j], dp[j - bags[i].time] + bags[i].color);
}
}
}
cout.println(dp[totalTime]);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class bag {
int time;
int color;
int blog;//0 为01背包 1 为完全背包
}
}
- 板子题练习
浙公网安备 33010602011771号