期中考终于考完了,整道题奖励下自己
我一北大同学问我的,说他递归超时了,叫我想一个办法
后面他说他加了个剪枝就过了,然后我自己尝试了一个方法:
就是先把城市按1到n排列,然后考虑互换,如果互换后更便宜就换
这样下去的排列一直最优化进行
最后不能最优的时候就ok了
代码如下:
#include<stdio.h>
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<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]);
//先计算总价钱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<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级最强新生)