1.回溯法
回溯法按深度优先策略搜索问题的解空间树,首先从根节点出发依次搜索解空间树进行遍历,搜索遍历过程中记录解,已至到最后求出最优解,都每一节点都利用剪枝函数判断该节点是否能继续往下搜索,也就是判断是否还会有解;如果可行,就继续向下搜索;如果不行,则跳过该节点所有可能继续向下的搜索。(行就接着往下搜,不行下面的就都不搜了)
剪枝函数是为了避免无效的搜索。剪枝函数一般:剪去不满足约束条件的,剪去已经确定不能得到最优解的。
2.练习
1.4×4的网格放碉堡,X表示墙壁,墙壁可以挡子弹,碉堡的子弹都走直线,保证所有的碉堡不相互摧毁。
(Fire Net 1002)
package com.lq.exercise06;
import java.util.*;
public class Exercise0601 {
static int n;
static char[][] c=new char[4][4];
static int num=0;
static int maxnum=0;
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
n=scan.nextInt();
while(n!=0){
for(int i=0;i<n;i++){
String s=scan.next();
for(int j=0;j<n;j++){
c[i][j]=s.charAt(j);
}
}
dfs(n);
System.out.println(maxnum);
n=scan.nextInt();
num=0;
maxnum=0;
}
}
public static boolean check(int x,int y){
for(int i=y+1;i<n;i++){
if(c[x][i]=='X'){
break;
}else if(c[x][i]=='0'){
return false;
}
}
for(int i=y-1;i>=0;i--){
if(c[x][i]=='X'){
break;
}else if(c[x][i]=='0'){
return false;
}
}
for(int i=x+1;i<n;i++){
if(c[i][y]=='X'){
break;
}else if(c[i][y]=='0'){
return false;
}
}
for(int i=x-1;i>=0;i--){
if(c[i][y]=='X'){
break;
}else if(c[i][y]=='0'){
return false;
}
}
return true;
}
public static void dfs(int n){
if(num>maxnum){
maxnum=num;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(c[i][j]=='X'||c[i][j]=='0'){
continue;
}else if(check(i,j)){
c[i][j]='0';
num++;
dfs(n);
c[i][j]='.';
num--;
}
}
}
}
}
2.ABCDEFGHIJK 11个固定的小农田, 根据输入选择其中的一部分,拼成整个要灌溉的农田,求的是灌溉所有农田
所需的最少入水口,11个小农田图片有入水口。(Farm Irrigation 2412)
package com.lq.exercise06;
import java.util.Scanner;
public class Exercise0602 {
static int n, m;
static node[][] src;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
while (n != -1 && m != -1) {
src=new node[n][m];
for (int i = 0; i < m; i++) {
String s = scan.next();
for (int j = 0; j < n; j++) {
src[i][j]=new node();
src[i][j].ch = s.charAt(j);
switch (src[i][j].ch) {
case 'A':
src[i][j].a = 1;
src[i][j].b = 1;
src[i][j].c = 0;
src[i][j].d = 0;
break;
case 'B':
src[i][j].a = 0;
src[i][j].c = 1;
src[i][j].d = 0;
break;
case 'C':
src[i][j].a = 1;
src[i][j].b = 0;
src[i][j].c = 0;
src[i][j].d = 1;
break;
case 'D':
src[i][j].a = 0;
src[i][j].b = 0;
src[i][j].c = 1;
src[i][j].d = 1;
break;
case 'E':
src[i][j].a = 0;
src[i][j].b = 1;
src[i][j].c = 0;
src[i][j].d = 1;
break;
case 'F':
src[i][j].a = 1;
src[i][j].b = 0;
src[i][j].c = 1;
src[i][j].d = 0;
break;
case 'G':
src[i][j].a = 1;
src[i][j].b = 1;
src[i][j].c = 1;
src[i][j].d = 0;
break;
case 'H':
src[i][j].a = 1;
src[i][j].b = 1;
src[i][j].c = 0;
src[i][j].d = 1;
break;
case 'I':
src[i][j].a = 1;
src[i][j].b = 0;
src[i][j].c = 1;
src[i][j].d = 1;
break;
case 'J':
src[i][j].a = 0;
src[i][j].b = 1;
src[i][j].c = 1;
src[i][j].d = 1;
break;
case 'K':
src[i][j].a = 1;
src[i][j].b = 1;
src[i][j].c = 1;
src[i][j].d = 1;
break;
}
src[i][j].flag=0;
}
}
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (src[i][j].flag == 0) {
ans++;
dfs(i, j);
}
}
}
System.out.println(ans);
n = scan.nextInt();
m = scan.nextInt();
}
}
public static void dfs(int x, int y) {
if (x < 0 || x >= m || y < 0 || y >= n) {
return;
}
src[x][y].flag = 1;
if (x - 1 >= 0 && src[x - 1][y].flag == 0 && src[x][y].b * src[x - 1][y].d == 1) {
dfs(x - 1, y);
}
if (x + 1 < m && src[x + 1][y].flag == 0 && src[x][y].d * src[x + 1][y].b == 1) {
dfs(x + 1, y);
}
if (y - 1 >= 0 && src[x][y - 1].flag == 0 && src[x][y].a * src[x][y - 1].c == 1) {
dfs(x, y - 1);
}
if (y + 1 < n && src[x][y + 1].flag == 0 && src[x][y].c * src[x][y + 1].a == 1) {
dfs(x, y + 1);
}
return;
}
}
class node {
char ch;
int flag;
int a, b, c, d;
}