期中考终于考完了,整道题奖励下自己
我一北大同学问我的,说他递归超时了,叫我想一个办法
后面他说他加了个剪枝就过了,然后我自己尝试了一个方法:
就是先把城市按1到n排列,然后考虑互换,如果互换后更便宜就换
这样下去的排列一直最优化进行
最后不能最优的时候就ok了
代码如下:
#include<stdio.h>
int cost[16][16];
int r[16];//routeint 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;}//先计算总价钱mfor(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++;}elser[b] ^= r[e] ^= r[b] ^= r[e];}}}printf("%d", m);return 0;
}
想象很美好,结果呢?
没过
因为如果互换后价格一样,你是换还是不换?
考虑换的话可能最后不是最优,不换的话最后也可能不是最优
所以两个都要试一下
这样就不如递归剪枝
(注:a ^= b ^= a ^= b; 可以使二者互换,但是使用场景较少)
代码如下:
#include<stdio.h>
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]);//先计算总价钱mfor(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<iostream>
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级最强新生)