回溯与DFS


回溯与DFS

VJUDGE

HUD1312 Red and Black

#include<iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int N=2e5 + 100;
char g[25][25];
char dfs_g[25][25];
char bfs_g[25][25];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
struct node{
	int x;
	int y;
};
int n,m;
int dfs_ans = 0;
void dfs(node nowat){
	if(dfs_g[nowat.x][nowat.y] == '.'){
		dfs_ans++;
		dfs_g[nowat.x][nowat.y] = '#';
		for(int i = 0;i < 4;i++){
			int nx = nowat.x + dir[i][0];
			int ny = nowat.y + dir[i][1];
			if(nx >= 1 && ny >= 1 && nx <= n && ny <= m){
				node newpoint;
				newpoint.x = nx;
				newpoint.y = ny;
				dfs(newpoint);
			}
		}
	}
}

int main(){
	// ios::sync_with_stdio(false);
	// cin.tie(0);cout.tie(0);
	while(cin >> m >> n){
		if(m == 0 && n == 0)break;
		node st;
		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= m;j++){
				cin >> g[i][j];
				dfs_g[i][j] = g[i][j];
				bfs_g[i][j] = g[i][j];
				if(g[i][j] == '@'){
					bfs_g[i][j] = '#';
					dfs_g[i][j] = '.';
					st.x = i;
					st.y = j;
				}
			}
		}

		//以下为dfs解法
		dfs_ans = 0;
		dfs(st);

		//以下为bfs解法
		queue<node>q;
		q.push(st);
		int bfs_ans = 1;
		while (q.size()){
			node fir = q.front();
			q.pop();
			for(int i = 0;i < 4;i++){
				int nx = fir.x + dx[i];
				int ny = fir.y + dy[i];
				if(nx >= 1 && ny >= 1 && nx <= n && ny <= m && bfs_g[nx][ny] == '.'){
						bfs_ans++;
						bfs_g[nx][ny] = '#';
						node newpoint;
						newpoint.x = nx;
						newpoint.y = ny;
						q.push(newpoint);
				}
			}
		}

		if(dfs_ans == bfs_ans) cout << bfs_ans << endl;
	}
	return 0;
}

HDU 2553 N皇后问题

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
const int N = 30;

bool r[N],c[N],L[N],R[N];
int a[N],n,ans;

inline bool check(int x,int y){
	if(x < 1 || x > n || y < 1 || y > n) return 0;
	if(r[x] || c[y] || L[y+x] || R[y-x+10]) return 0;
	return 1;
}

inline void dfs(int x){
  	if(x > n){
  		ans++;
  		//for(int i = 1;i <= n;++i) printf("%5d",a[i]);
  		//printf("\n");
  		return;
	}
	
	for(int i = 1;i <= n;++i){
		if(check(x,i)){
			r[x] = c[i] = 1;
			L[i+x] = R[i-x+10] = 1;
			
			a[x] = i;
			dfs(x+1);
			
			r[x] = c[i] = 0;
			L[i+x] = R[i-x+10] = 0;
		}
	}
	return ;
}
int res[11] = {0};
int main() {
	res[1] = 1;
	res[2] = 0;
	res[3] = 0;
	for(int i=4;i<=10;i++){
		n = i;
		ans = 0;
		dfs(1);
		res[i] = ans;
	}
	while(~scanf("%d",&n)&&n){
		cout << res[n] << '\n';
	}
	return 0;
}

HDU 1175 连连看

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e3 + 5;

int d[4][2] = {                          // 方向数组
    {0, 1}, {0, -1}, {1, 0}, {-1, 0}
};

int n, m, q, g[MAXN][MAXN];
bool ok, vis[MAXN][MAXN];

bool ing(int x, int y) {                   // 判断(x, y)是否在网格内并且还没被访问过
    return 1 <= x && x <= n && 1 <= y && y <= m && !vis[x][y];
}

int sx, sy, ex, ey;                     // 起点终点用全局变量保存方便使用
void dfs(int x, int y, int dir, int cnt) {
    if (cnt > 2 || ok) return ;                         // 如果转向次数大于2次或者已经找到一条满足条件的路径直接返回
    if (cnt == 2 && (x != ex && y != ey)) return ;      // 如果转向次数已经两次但是当前点和终点还不在一条直线上直接返回
    if (x == ex && y == ey && cnt <= 2) {               // 如果到达终点并且转向次数小于等于2次将ok标记为true并返回
        ok = true;
        return ;
    }
    for (int i = 0; i < 4; ++i) {
        int nx = x + d[i][0];
        int ny = y + d[i][1];
        if (ing(nx, ny) && ((nx == ex && ny == ey) || !g[nx][ny])) {   // 下一个点是否在网格内并且是终点或者0点
                                                                        // 判断条件(nx == ex && ny == ey)不能写成(g[nx][ny] == g[ex][ey])
            vis[nx][ny] = true;                              // 对下一个点进行标记
            if (dir == -1 || dir == i) dfs(nx, ny, i, cnt);  // 如果是第一次走或者和上次方向一样cnt不增加
            else dfs(nx, ny, i, cnt + 1);                    // 否则增加
            vis[nx][ny] = false;                             // 回溯
        }
    }
}
int main(int argc, char *argv[]) {
    while (~scanf("%d%d", &n, &m) && n && m) {
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                scanf("%d", &g[i][j]);
        cin >> q;
        while (q--) {
            scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
            if (g[sx][sy] == g[ex][ey] && g[sx][sy] && g[ex][ey]) {   // 两个点相等并且不为0
                memset(vis, false, sizeof(vis));            // 初始化
                ok = false;                                 // 初始化
                vis[sx][sy] = true;
                dfs(sx, sy, -1, 0);
                printf("%s\n", ok ? "YES" : "NO");
            } else printf("NO\n");
        }
    }
    //system("pause");
    return 0;
}

HDU 5113 Black And White

#include <iostream>
#include <cstring>
using namespace std;
const int N=2e5 + 100;
int a[10][10];
int c[100];
bool fin;
int n,m,k;
bool check(int x,int y,int c){
	if(a[x - 1][y] == c || a[x][y - 1] == c){
		return false;
	}
	return true;
}
void dfs(int x,int y,int left){
	if(fin || ed) return ;
	if(left == 0){
		fin = true;
		return ;
	}
	for(int i = 1;i <= k;i++){
		if((left + 1)/ 2 < c[i])return ;
	}
	for(int i = 1;i <= k;i++){
		if(c[i] == 0)continue;
		if(!check(x,y,i))continue ;
		a[x][y] = i;
		c[i]--;
		if(y == m)dfs(x + 1,1,left - 1);
		else dfs(x,y+1,left - 1);
		if(fin)return ;
		c[i]++;
	}
}
int main(){
	int t;
	cin >> t;
	for(int cas = 1;cas <= t;cas++){
		cin >> n >> m >> k;
		fin = false;
		memset(a,0,sizeof a);
		for(int i = 1;i <= k;i++){
			cin >> c[i];
		}
		dfs(1,1,n * m);
		printf("Case #%d:\n",cas);
		if(fin){
			printf("YES\n");
			for(int i = 1;i <= n;i++){
				for(int j = 1;j <= m;j++){
					printf("%d",a[i][j]);
					if(j != m)printf(" ");
					else printf("\n");
				}
			}
		}else printf("NO\n");
	}
}

POJ 2531 Network Saboteur

#include<iostream>
using namespace std;
int net[25][25];
int vis[25];
int ans;
int n,p = 0,cnt;
void dfs(int x,int sum){
	if(x == n){
		ans = max(ans, sum);
		return;
	}
	int cnt = 0;
	for(int j = 0;j < x;j++){
		if(vis[j] == 0) cnt += net[x][j];
	}
	vis[x] = 1;
	dfs(x + 1,sum + cnt);
	
	cnt = 0;
	for(int j = 0;j < x;j++){
		if(vis[j]) cnt += net[x][j];
	}
	vis[x] = 0;
	dfs(x + 1,sum + cnt);
}
int main(){
	cin >> n;
	for(int i = 0;i < n;i++){
		for(int j = 0;j < n;j++){
			cin >> net[i][j];
		}
	}
	ans = 0;
	dfs(0, 0);
	cout << ans << endl;	
	return 0;
}
#include<iostream>
using namespace std;
int net[25][25];
int main(){
	int n;
	cin >> n;
	for(int i = 0;i < n;i++){
		for(int j = 0;j < n;j++){
			cin >> net[i][j];
		}
	}
	int ans = 0;
	int tans, tn;
	for(int cas = 0;cas < 1<<(n - 1);cas++){
		tn = cas; tans = 0;
		for(int idx = 0;idx < n;idx++){
			if(tn >> idx & 1){
				for(int tidx = 0;tidx < idx;tidx++){
					if((tn >> tidx) % 2 == 0){
						tans += net[idx][tidx];
					}
				}
			}else{
				for(int tidx = 0;tidx < idx;tidx++){
					if(tn >> tidx & 1){
						tans += net[idx][tidx];
					}
				}
			}
		}
		ans = max(ans,tans);
	}
	cout << ans << endl;
	system("pause");
	return 0;
}

POJ 1416 Shredding Company

#include <iostream>
using namespace std;
string project;
int n, ans;
bool is_unique, is_exist;
int str_to_int(string s){
	int res = 0;
	for(int i = 0;i<s.length();i++){
		res *= 10;
		res += (s[i] - '0');
	}
	return res;
}
void dfs(int sum, string s, string nowpro){
	if(s.length() == 0){
		if(sum > ans){
			ans = sum;
			project = nowpro;
			is_exist = true;
			is_unique = true;
		}else if(sum == ans){
			is_unique = false;
		}
		return ;
	}
	for(int i = 1;i <= s.length();i++){
		string pt = s.substr(0,i);
		//cout  << "pt" << pt << endl;
		if(sum + str_to_int(pt) <= n){
			string prepro = nowpro;
			nowpro += " ";
			nowpro += pt;
			dfs(sum + str_to_int(pt),s.substr(i),nowpro);
			nowpro = prepro;
		}
	}
}
int main(){
	string ss;
	while(cin >> n >> ss){
		if(n == 0 && ss == "0")break;
		ans = 0;
		is_unique = false;
		is_exist = false;
		dfs(0,ss,"");
		if(is_unique && is_exist){
			cout << ans << project << endl;
		}else if(is_exist){
			cout << "rejected" << endl;
		}else{
			cout << "error" << endl;
		}
	}
	system("pause");
}

POJ 2676 Sudoku

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int sudoku[10][10];

int column[10][10];
int row[10][10];
int box[10][10];

struct node{
	int x,y;
};
node nvis[105];
char s[15][15];
bool fin = false;
int num = 0;
int getbox(int x,int y){
	return (x-1)/3*3 + (y-1)/3 + 1; 
}

void put(int x,int y,int tn,int f){
	if(f) sudoku[x][y] = tn;
	column[y][tn] = f;
	row[x][tn] = f;
	box[getbox(x,y)][tn] = f;
}

int can(int x,int y,int tn){
	if(row[x][tn]) return 0;
	if(column[y][tn]) return 0;
	if(box[getbox(x,y)][tn]) return 0;
	return 1;
}

int cmp(node a,node b){
    return a.y>b.y;
}

void dfs(int k){
	if(fin) return ;
	if(k == num + 1){
		for(int i = 1;i <= 9;i++){
			for(int j = 1;j <= 9;j++){
				if(j == 9){
					printf("%d\n",sudoku[i][j]);
				}else{
					printf("%d",sudoku[i][j]);
				}
			}
		}
		fin = true;
	}
	for(int nm = 1;nm <= 9;nm++){
		if(can(nvis[k].x,nvis[k].y,nm)){
			put(nvis[k].x,nvis[k].y,nm,1);
			dfs(k+1);
			put(nvis[k].x,nvis[k].y,nm,0);
		}
	}
}

void init(){
	fin = 0;
	num = 0;
	memset(sudoku,0,sizeof(sudoku));
	memset(row,0,sizeof(row));
	memset(column,0,sizeof(column));
	memset(nvis,0,sizeof(nvis));
	memset(box,0,sizeof(box));
}

int main(){
	int cnt;
	cin >> cnt;
	while(cnt--){
		init();
		for(int i = 1;i <= 9;i++){
			scanf("%s",s[i] + 1);
			for(int j = 1;j <= 9;j++){
				if(s[i][j] == '0'){
					nvis[++num].x = i;
					nvis[num].y = j;
				}else{
					put(i,j,s[i][j] - '0',1);
				}
			}
		}
		dfs(1);
	}
	//system("pause");
	return 0;
}

POJ 1129 Channel Allocation

#include <iostream>
#include <cstring>
using namespace std;
int edge[30][30];
int c[30];
int n,k;
bool ok;
void dfs(int x){
	if(ok)return ;
	if(x > n){
		ok = true;
		return ;
	}
	//当前点染上什么颜色
	for(int i = 1;i <= k;i++){
		c[x] = i;//染上这种颜色
		int f = 1;
		//遍历所有边,看看有边相连的点中有没有这种颜色
		for(int j = 1;j < x;j++){
			if(j == x)continue;
			if(edge[x][j] == 1){
				if(c[j] == c[x]){
					f = 0;
					break;
				}
			}
		}
		if(f){
			dfs(x + 1);
		}
	}
	return ;
}
int main(){
	while(cin >> n){
		memset(edge, 0, sizeof edge);
		if(n == 0)break;
		string s;
		for(int i = 1;i <= n;i++){
			cin >> s;
			for(int j = 2;j < s.length();j++){
				edge[s[0] - 'A' + 1][s[j] - 'A' + 1] = 1;
				edge[s[j] - 'A' + 1][s[0] - 'A' + 1] = 1;
			}
		}
		ok = false;
		for(k = 0;;k++){
			memset(c, 0, sizeof c);
			dfs(1);
			if(ok){
				if(k == 1) cout << k << " channel needed.\n";
				else cout << k << " channels needed.\n";
				break;
			}
		}
	}
	system("pause");
}

WLACM

A 全排列问题

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5;
bool vis[N];
int n,a[N];
inline void dfs(int step){
	if(step == n){
		for(int i = 0;i < n;i++)
			printf("%5d",a[i]);
		printf("\n");
		return ; 
	}
	for(int i = 1;i <= n;i++){
		if(vis[i]) continue;
		vis[i] = 1;
		a[step] = i;
		dfs(step + 1);
		vis[i] = 0;
	}
}
int main(){
	scanf("%d",&n);
	dfs(0);
	return 0;
} 

B 输出N个不同字母的全排列

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5;
bool vis[N];
int n, a[N];
inline void dfs(int step){
	if (step == n){
		for (int i = 0; i < n; i++)
			printf("%c", a[i] + 'A' - 1);
		printf("\n");
		return;
	}
	for (int i = 1; i <= n; i++){
		if (vis[i])
			continue;
		vis[i] = 1;
		a[step] = i;
		dfs(step + 1);
		vis[i] = 0;
	}
}
int main(){
	scanf("%d", &n);
	dfs(0);
	return 0;
}

C 排列棋子

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5;
int n, m;
bool vis[N];
int a[N];
int q[N];
int step;
int f = 1;
inline void dfs(int step){
	if (step == n + m){
		for (int i = 0; i < n + m; i++)
			printf("%d", a[i]);
		printf("\n");
		f = 0;
		return;
	}
	for (int i = 0; i < n + m; i++){
		if (vis[i] == 0 && (a[step] != q[i] || f)){
			f = 1;
			vis[i] = 1;
			a[step] = q[i];
			dfs(step + 1);
			vis[i] = 0;
		}
	}
}
int main(){
	cin >> m >> n;
	for (int i = 0; i < m; i++){
		q[i] = 0;
	}
	for (int i = m; i < n + m; i++){
		q[i] = 1;
	}
	dfs(step);
	return 0;
}

D 组合的输出

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5;
int n,m;
bool vis[N];
int a[N];
int step;
inline void dfs(int num,int step){
	if(step == n){
		for(int i = 0;i < n;i++)
			printf("%3d",a[i]);
		printf("\n");
		return ; 
	}
	for(int i=num;i <= m;i++){
		if(vis[i] == 0){
			vis[i] = 1;
			a[step] = i;
			dfs(i,step + 1);
			vis[i] = 0;
		}
		
	}
}
int main(){
	cin >> m >> n;
	dfs(1,step);
	return 0;
} 

E 有重复元素的排列问题

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[600], f[30];
int k = 0;
void dfs(int step){
    if (step == n + 1){
        for (int i = 1; i <= n; i++)
            printf("%c", a[i] + 'a');
        printf("\n");
        k++;
        return;
    }
    for (int i = 0; i < 26; i++){
        if (f[i] > 0){
            f[i]--;
            a[step] = i;
            dfs(step + 1);
            f[i]++;
        }
    }
}
int main(){
    string s;
    cin >> n >> s;
    for (int i = 0; i < n; i++){
        f[s[i] - 'a']++;
    }
    dfs(1);
    cout << k << endl;
    return 0;
}

F 集合划分问题

#include<iostream>
using namespace std;
typedef unsigned long long ll; 
ll f(ll n, ll m) {
	if (m == 1 || n == m) {
		return 1;
	}
	else {
		return f(n - 1, m - 1) + m * f(n - 1, m);
	}
}
 
int main() {
	ll n, m;
	scanf("%lld %lld", &n, &m);
	printf("%lld", f(n, m));
	return 0;
}

G 数的计数

#include <iostream>
using namespace std;
const int maxn = 1005;
int n,f[maxn]={1},ans;
int main(){
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
		for(int j = 0;j <= i/2;j++)
			f[i] += f[j];
	cout << f[n] << endl;
	return 0;
}

H 简单背包问题

#include <bits/stdc++.h>
using namespace std;
int n,s; 
int a[1000] = {0};
int b[1000] = {0};
int bag(int s,int n){ // 假设背包里面以及有s的物品,拿出来 
    if(s == 0)  // 背包正好空了 
        return true;
    else if(s != 0 && n == 0) // 东西全放进去 也不到s 
        return false;
    else if(bag(s-a[n-1],n-1))  {
        printf("number:%d  weight:%d\n",n,a[n-1]);
        return true;
    }
    return bag(s,n-1);
}
  
int main(){
    cin >> n >> s;
    for(int i = 0; i < n; i++) cin >> a[i];
    if(!bag(s,n)){
        cout << "not found" << endl;
    }
	system("pause");
    return 0;
	
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM