02 回溯算法

一、N皇后问题

import java.util.ArrayList;
import java.util.Scanner;

class solveNQueens {
    //存储结果
    public static ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>();

    public static void main(String args[]) {
        int n;
        Scanner input = new Scanner(System.in);
        n = input.nextInt();
        ArrayList<ArrayList<String>> result = solveNQueens(n);
        for (int k = 0; k < result.size(); k++) {
            for (int i = 0; i < n; i++) {
                String string = result.get(k).get(i);
                for (int j = 0; j < string.length(); j++) {
                    System.out.print(string.charAt(j));
                    if (j != string.length() - 1) {
                        System.out.print(' ');
                    }
                }
                System.out.println();
            }
            if (k != result.size() - 1) System.out.println();
        }
    }

    public static ArrayList<ArrayList<String>> solveNQueens(int n) {
        int a[][] = new int[n][n];
        solve(a, n, 0);
        return list;
    }

    public static void solve(int a[][], int n, int num) {
        for (int j = 0; j < n; j++) {
            if (a[num][j] == 0 && ifDown(a, num, j, n)) {//判断是否可以落点
                a[num][j] = 1;//落子
                if (num >= n - 1) {//判断是否是符合要求的结果
                    addList(a);//记录符合要求的结果
                    a[num][j] = 0;//恢复棋盘
                    return;
                } else solve(a, n, num + 1);//递归,落下一个皇后
                a[num][j] = 0;//恢复棋盘
            }
        }
    }

    public static void addList(int a[][]) {
        ArrayList<String> li = new ArrayList<String>();
        for (int i = 0; i < a.length; i++) {
            StringBuilder str = new StringBuilder();
            for (int j = 0; j < a.length; j++) {
                if (a[i][j] == 0) str.append('.');
                else if (a[i][j] == 1) str.append('Q');
            }
            li.add(str.toString());
        }
        list.add(li);
    }

    //判断某点是否可以落子
    public static boolean ifDown(int a[][], int x, int y, int n) {
        //上
        for (int i = x; i >= 0; i--) {
            if (a[i][y] != 0) return false;
        }
        //左上
        for (int i = x, j = y; i >= 0 && j >= 0; i--, j--) {
            if (a[i][j] != 0) return false;
        }
        //右上
        for (int i = x, j = y; i >= 0 && j < n; i--, j++) {
            if (a[i][j] != 0) return false;
        }
        return true;
    }
}

二、迷宫问题

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 1010
char mapp[MAXN][MAXN];
int visit[MAXN][MAXN];
int dirx[4] = { -1,0,0,1 };
int diry[4] = { 0,1,-1,0 };
int n, k;
int c = 0;
struct Node
{
	int x, y, step;
};
queue<Node> q;
Node treasure[20];
int cheak(struct Node X)
{
	if (X.x < 0 || X.x >= n || X.y < 0 || X.y >= n || mapp[X.x][X.y] == '#' || visit[X.x][X.y] == 1)
		return 0;
	return 1;
}
int bfs(Node first, Node last)
{
	while (!q.empty())
	{
		q.pop();
	}
	Node a, b;
	a.x = first.x, a.y = first.y, a.step = 0;
	q.push(a);
	while (!q.empty())
	{
		a = q.front();
		q.pop();
		if (a.x == last.x && a.y == last.y)
			return a.step;//这里不应该直接返回,应该用个数组之类的保存,然后取该程序的最小值,测试用例不过关,取巧了o.o
		for (int i = 0; i < 4; i++)
		{
			b.x = a.x + dirx[i];
			b.y = a.y + diry[i];
			if (cheak(b))
			{
				b.step = a.step + 1;
				for (int i = 0; i < k; i++)
				{
					if (b.x == treasure[i].x && b.y == treasure[i].y && (mapp[first.x][first.y]!='a'+i )&&( mapp[last.x][last.y] != 'a' + i))
					{
						b.step++;
						break;
					}
				}
				visit[b.x][b.y] = 1;
				q.push(b);
			}
		}
	}
	return -1;
}
int main()
{
	int sum = 0;
	Node beginn, destt;
	scanf("%d %d", &n, &k);
	for (int i = 0; i < n; i++)
	{
		getchar();
		for (int j = 0; j < n; j++)
		{
			scanf("%c", &mapp[i][j]);
			if (mapp[i][j] == 'S')
			{
				beginn.x = i;
				beginn.y = j;
			}
			if (mapp[i][j] == 'G')
			{
				destt.x = i;
				destt.y = j;
			}
			if (mapp[i][j] >= 'a'&&mapp[i][j] <= 'z')
			{
				treasure[mapp[i][j] - 'a'].x = i;
				treasure[mapp[i][j] - 'a'].y = j;
			}
		}
	}
	memset(visit, 0, sizeof(visit));
	int temp = bfs(beginn, treasure[0]);
	if (temp != -1)
		sum += temp;
	else
		return 0;
	//printf("%d %d\n", sum,c);
	for (int i = 0; i < k - 1; i++)
	{
		memset(visit, 0, sizeof(visit));
		temp = bfs(treasure[i], treasure[i + 1]);
		if (temp != -1)
			sum += temp;
		else
			return 0;
		//printf("%d\n", sum);
	}
	memset(visit, 0, sizeof(visit));
	temp = bfs(treasure[k - 1], destt);
	if (temp != -1)
		sum += temp;
	else
		return 0;
	printf("%d\n", sum + k);
	return 0;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值