思路:和捡一次的思路一样,变化的部分是,因为需要进行第二次捡拾,第一次捡拾的路径需要被记录。
实现的时候,把每一个节点的父亲节点保存一下,第一次捡完后,从最后一个节点回溯下,父亲路径上的废纸清除。
疑问:两次局部最优解,是否是全局最优解?因为代码没提交,只检查了两个用例,无法确定
package info.frady.dp;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
2020.03.22
* 可以行走,有废纸
。可以行走,但没有废纸
#不可以行走
2
9 7
*........
.....**#.
..**...#*
..####*#.
.*.#*.*#.
...#**...
*........
5 5
.*.*.
*###.
*.*.*
.###*
.*.*.
7
8
1
5 5
.*.*.
*###.
*.*.*
.###*
.*.*.
*/
public class 捡两次废纸_范贤捡废纸 {
public static void main(String[] args) throws Exception{
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int T=Integer.parseInt(reader.readLine());//测试用例的个数
for (int i = 0; i < T; i++) {
String str=reader.readLine();
int L=Integer.parseInt(str.split(" ")[0]);//存放数据的列
int H=Integer.parseInt(str.split(" ")[1]);//存放数据的行
char [][] arr1=new char[H][L];//存放数据的开始状态
char [][] arr2=new char[H][L];//存放纸片被捡走后,第二次的数据状态
for (int j = 0; j <H ; j++) {
str=reader.readLine();
for (int k = 0; k <L ; k++) {
arr1[j][k]=str.charAt(k);
arr2[j][k]=str.charAt(k);
}
}
int f1=process(arr1,arr2);
int f2=process(arr2,arr1);
System.out.println(f1+f2);
}
reader.close();
}
private static int process(char[][] arr1,char[][] arr2) {
int H=arr1.length;
int L=arr1[0].length;
int [][] r=new int[H][L];
int[][] ph=new int[H][L];//保存当前节点的父亲节点
int[][] pl=new int[H][L];//保存当前节点的父亲节点
for (int j = 0; j < H; j++) {//行
for (int k = 0; k < L; k++) {//列
int l=0;
int u=0;
if(k-1>=0 ){//左侧有数据
l= r[j][k-1];
}
if(j-1>=0 ){//上方有数据
u= r[j-1][k];
}
if(arr1[j][k]=='#'){
r[j][k]=-Integer.MAX_VALUE;
}else{//当前不是死路,需要选择最好的路径
int max=0;
if(l>=u){//左侧的数据大,选择左侧的数据,路径从左侧来
max=l;
ph[j][k]=j;//父节点所在的行
pl[j][k]=k-1;
}else{//上方数据比较大,选择上方的数据,道路从上方来
max=u;
ph[j][k]=j-1;//父节点所在的行
pl[j][k]=k;
}
if(arr1[j][k]=='*' ) {//有废纸
r[j][k]=max+1;
}else{
r[j][k]=max;
}
}
}
}
//需要把最长的路径上的废纸捡掉,用arr1捡掉后,生成arr2
arr2[arr2.length-1][arr2[0].length-1]='.';//最后一个点肯定被访问到
arr2[0][0]='.';//第一个点肯定被访问到
int m=H-1;
int n=L-1;
while(m!=0 && n!=0){
arr2[ph[m][n]][pl[m][n]]='.';
m=ph[m][n];
n=pl[m][n];
}
return r[r.length-1][r[0].length-1];
}
}