UVa 140 Bandwidth 带宽

“剪枝” --本题的优化方案

  1. 可以记录下目前已经找到的最小带宽k。如果发现已经有某两个结点的距离大于或等于k,再怎么扩展也不可能比当前解更优,应当强制把它“剪”掉,就像园丁在花园里为树修剪枝叶一样,也可以为解答树“剪枝(prune)”。
  2. 除此之外,还可以剪掉更多的枝叶。如果在搜索到结点u时,u结点还有m个相邻点没有确定位置,那么对于结点u来说,最理想的情况就是这m个结点紧跟在u后面,这样的结点带宽为m,而其他任何“非理想情况”的带宽至少为m+1。这样,如果m≥k,即“在最理想的情况下都不能得到比当前最优解更好的方案”,则应当剪枝。

这个代码好像就是全排列了,没有什么优化,剪枝吧?

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 10;
int id[256], letter[maxn];

int main()
{
	char input[1000];
	while(scanf("%s", input) == 1 && input[0] != '#') 
	{
		// 计算结点个数并给字母编号
		int n = 0;
	    for(char ch = 'A'; ch <= 'Z'; ch++)
	    	if(strchr(input, ch) != NULL) 
			{
		        id[ch] = n++;  //编号 
		        letter[id[ch]] = ch;  //编号 对应记录 
	    	}
    	
    	// 处理输入
    	int len = strlen(input), p = 0, q = 0;
    	vector<int> u, v;
    	for(;;)
    	{	//真心不错的字符串处理 
    		while(p < len && input[p] != ':') p++;
	    	if(p == len) break;
	    	while(q < len && input[q] != ';') q++;
	    	for(int i = p+1; i < q; i++) 
			{
		        u.push_back(id[input[p-1]]);
		        v.push_back(id[input[i]]);
			}
			p++;q++;
		}
		
		//“剪枝 ”对解答树而言  感觉这个代码没有剪枝 
		//枚举全排列
		int P[maxn], bestP[maxn], pos[maxn], ans = n;
		for(int i = 0; i < n; i++)	P[i] = i;	//生成全排列用的原排列 
		do{
			for(int i = 0; i < n; i++) pos[P[i]] = i; //给新排列编位置 
			int bandwidth = 0;
			for(int i = 0; i < u.size(); i++)	
				bandwidth = max(bandwidth, abs(pos[u[i]] - pos[v[i]])); // 计算带宽
			if(bandwidth < ans)
			{
		        ans = bandwidth;
		        memcpy(bestP, P, sizeof(P));
      		}
		}while(next_permutation(P, P+n));
		
		// 输出
	    for(int i = 0; i < n; i++) printf("%c ", letter[bestP[i]]);
	    printf("-> %d\n", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值