递归剪枝题

期中考终于考完了,整道题奖励下自己

递归剪枝题_第1张图片

我一北大同学问我的,说他递归超时了,叫我想一个办法

后面他说他加了个剪枝就过了,然后我自己尝试了一个方法:

就是先把城市按1到n排列,然后考虑互换,如果互换后更便宜就换

这样下去的排列一直最优化进行

最后不能最优的时候就ok了

代码如下:

#include
int cost[16][16];
int r[16];//route

int main(void)
{
    int n, m = 0, count = 1;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
            scanf("%d", &cost[i][j]);
        r[i] = i;
    }
    //先计算总价钱m
    for(int i = 1; i < n; i++)
        m += cost[i][i + 1];
    m += cost[1][n];
    //开始找最优解
    while(count)
    {
        count = 0;
        for(int b = 1; b < n; b++)
        {
            int a = (b == 1) ? n : b - 1;
            int c = b + 1;
            for(int e = b + 1; e <= n; e++)
            {
                int d = e - 1;
                int f = (e == n) ? 1 : e + 1;
                int former = cost[r[a]][r[b]] + cost[r[b]][r[c]] + cost[r[d]][r[e]] + cost[r[e]][r[f]];
                r[b] ^= r[e] ^= r[b] ^= r[e];
                int later = cost[r[a]][r[b]] + cost[r[b]][r[c]] + cost[r[d]][r[e]] + cost[r[e]][r[f]];
                if(former > later)
                {
                    m -= former - later;
                    count++;
                }
                else
                    r[b] ^= r[e] ^= r[b] ^= r[e];
            }
        }
    }
    printf("%d", m);

    return 0;
}

想象很美好,结果呢?

没过

因为如果互换后价格一样,你是换还是不换?

考虑换的话可能最后不是最优,不换的话最后也可能不是最优

所以两个都要试一下

这样就不如递归剪枝

(注:a ^= b ^= a ^= b; 可以使二者互换,但是使用场景较少)

代码如下:

#include
void dg(int x, int c);
int cost[16][16], city[16], r[16];//city route
int n, m;

int main(void)
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            scanf("%d", &cost[i][j]);

    //先计算总价钱m
    for(int i = 1; i < n; i++)
        m += cost[i][i + 1];
    m += cost[1][n];
    dg(1, 0);
    
    printf("%d", m);

    return 0;
}
void dg(int x, int c)//c为cost
{
    for(int i = 1; i <= n; i++)
        if(!(city[i]))
        {
            if(x == 1)
            {
                city[i] = 1, r[x] = i;
                dg(x + 1, 0);
                city[i] = 0, r[x] = 0;
            }
            else if(x == n)
            {
                c += cost[i][r[x - 1]] + cost[i][r[1]];
                m = (c > m) ? m : c;
                c -= cost[i][r[x - 1]] + cost[i][r[1]];
            }
            else
            {
                c += cost[i][r[x - 1]];
                if(c <= m)
                {
                    city[i] = 1, r[x] = i;
                    dg(x + 1, c);
                    city[i] = 0; r[x] = 0;
                }
                c -= cost[i][r[x - 1]];
            }
        }
    return;
}

后面还是超时

不知道为什么,思路和我同学都一样

代码如下:

#include
using namespace std;
int n;
int a[15][15];
int b[15]{};
int i, j, k;
int c = 0;
int cost(int c1,int i) {
    if(c1>=c){
        return 0;
    }
	int j;
	int flag = 0;
	for (j = 0; j < n; j++) {
		if (b[j] == 0) {
			flag = 1;
			b[j] = 1;
			cost(c1 + a[i][j], j);
			b[j] = 0;
		}
	}
	if (flag == 0) {
		c1 += a[i][0];
		if (c1 < c) {
			c = c1;
		}
	}
	return 0;
}
int main() {
	cin >> n;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			cin >> a[i][j];
		}
	}
	for (i = 0; i < n; i++) {
		if (i < n - 1) {
			c += a[i][i + 1];
		}
		else {
			c += a[i][0];
		}
	}
	b[0]=1;
	cost(0,0);
	cout << c << endl;
	return 0;
}

(引自北京大学2023级最强新生)

你可能感兴趣的:(剪枝,算法,机器学习)