Bandwidth UVA - 140 (枚举排列:对解答树剪枝)

题目链接

题目大意:

给出一个n(n≤8)个结点的图G和一个结点的排列,定义结点i的带宽b(i)为i和相邻结点 在排列中的最远距离,而所有b(i)的最大值就是整个图的带宽。给定图G,求出让带宽最小 的结点排列。

分析:

可以记录下目前已经找到的最小带宽k。如果发现已经有某两个结点的距离大于或等 于k,再怎么扩展也不可能比当前解更优,应当强制把它“剪”掉。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
int matrix[maxn][maxn];
int min_arr[maxn];
int arr[maxn];
bool vis[maxn];
int n, ans;

void dfs(int cur) {
	int dis = 0;
	if(cur==n) {
		for(int i = 0; i < n-1; i++) {
			for(int j = i+1; j < n; j++) {
				if(matrix[arr[i]][arr[j]]) {
					if((j-i)>dis) dis = (j-i);
				}
			}
		}
		if(ans>dis) {
			ans = dis;
			for(int i = 0; i < n; i++)
				min_arr[i] = arr[i];
		}
		return;
	}
	else {
		for(int i = 0; i < 26; i++) {
			if(vis[i]) {
				bool ok = true;
				for(int j = 0; j < cur; j++) {
					if(matrix[i][arr[j]]) {
						//当前已有两个结点的距离大于ans,对解答树剪枝
						if(cur-j>ans) {
							ok = false;
							break;
						}
					}
				}
				if(ok) {
					vis[i] = false;
					arr[cur] = i;
					dfs(cur+1);
					vis[i] = true;//辅助数组要恢复
				}
			}
		}
	}
}

int main() {
	freopen("i.txt","r",stdin);
    freopen("o.txt","w",stdout);
    string str,s;
    while(cin >> str && str!="#") {
    	memset(vis, false, sizeof(vis));
    	memset(min_arr, 0, sizeof(min_arr));
    	memset(matrix, 0, sizeof(matrix));
    	n = 0, ans = INT_MAX;
    	for(int i = 0; i < (int)str.length(); i++) {
    		if(isalpha(str[i]) && !vis[str[i]-'A']) {
    			arr[n++] = str[i];
    			vis[str[i]-'A'] = true;
    		}
    	}	
    	for(int i = 0; i < (int)str.length(); i++) {
    		if(str[i]==';') str[i] = ' ';
    	}
    	stringstream ss(str);
    	while(ss>>s) {
    		for(int i = 2; i < (int)s.length(); i++)
    			matrix[s[0]-'A'][s[i]-'A'] = matrix[s[i]-'A'][s[0]-'A'] = 1;
    	}
    	dfs(0);
 		for(int i = 0; i < n; i++)
 			cout << char(min_arr[i]+'A') <<" ";
 		cout << "-> " << ans << endl;
    }
    return 0;
}

第一次没有剪枝做的,一直wa但没有判TLE不知道为啥。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
vector<int> vec[maxn];
int min_arr[maxn];
int arr[maxn];
bool vis[maxn];
int n, mmin;

int Judge(int n) {
	int m = 0;
	for(int i = 0; i < n; i++) {
    	auto it1 = find(arr, arr+n, i);
    	for(int j = 0; j < (int)vec[i].size(); j++) {
			auto it2 = find(arr, arr+n, vec[i][j]);    		
			if(abs(it2-it1)>m) m = abs(it2-it1);	
    	}
    }
    return m;
}

int main() {
    string str,s;
    while(cin >> str && str!="#") {
    	memset(vis, false, sizeof(vis));
    	memset(min_arr, 0, sizeof(min_arr));
    	mmin = 0;
    	for(int i = 0; i < maxn; i++) vec[i].clear();
    	n = 0;
    	for(int i = 0; i < (int)str.length(); i++) {
    		if(isalpha(str[i]) && !vis[str[i]-'A']) {
    			arr[n++] = str[i]-'A';
    			vis[str[i]-'A'] = true;
    		}
    	}	
    	for(int i = 0; i < (int)str.length(); i++) {
    		if(str[i]==';') str[i] = ' ';
    	}
    	stringstream ss(str);
    	while(ss>>s) {
    		for(int i = 2; i < (int)s.length(); i++)
    			vec[s[0]-'A'].push_back(s[i]-'A');
    	}
    	sort(arr, arr+n);
    	mmin = maxn*maxn;
 		do{
 			if(mmin>Judge(n)) {
 				mmin = Judge(n);
 				for(int i = 0; i < n; i++)
 					min_arr[i] = arr[i];
 			}
 		}while(next_permutation(arr, arr+n));
 		for(int i = 0; i < n; i++)
 			cout << char(min_arr[i]+'A') <<" ";
 		cout << "-> " << mmin << endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值