邮局
题中的数据量很小,但单纯的回溯会超时,所以需要剪枝,这里减了三个枝。
1.当即使所有剩余点都算上都不能取k个点时。
2.当当前点大于k个时。
3.当发现加入一个点后距离数组没有变化时,说明这个点可有可无以后不再计算。
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAXN = 100, INF = 0x3f3f3f3f;
int n, m, k;
struct node {
int x, y;
}house[MAXN], post[MAXN];
double c[MAXN][MAXN];
bool vis[MAXN];
vector<int>vet;
double ans = 0x3f3f3f3f;
double dist[MAXN];
void dfs(int pos, double sum,int num, vector<int>v) {
if (num + (m - pos + 1) < k)return;
if (num > k)return;
if (num == k) {
if (ans > sum) {
ans = sum;
vet = v;
}
return;
}
dfs(pos + 1, sum, num, v);
if (vis[pos])return;
double temp[MAXN];
memcpy(temp, dist, sizeof(temp));
int flag = 0;
for (int i = 1; i <= n; i++)
if (dist[i] > c[pos][i]) {
dist[i] = c[pos][i];
flag = 1;
}
sum = 0;
for (int i = 1; i <= n; i++) {
sum += dist[i];
}
if (flag) {
v.push_back(pos);
dfs(pos + 1, sum, num + 1, v);
memcpy(dist, temp, sizeof(dist));
v.pop_back();
}
else vis[pos] = 1;
}
int main() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
cin >> house[i].x >> house[i].y;
for (int i = 1; i <= m; i++)
cin >> post[i].x >> post[i].y;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
c[i][j] = sqrt((post[i].x - house[j].x)*(post[i].x - house[j].x) + (post[i].y - house[j].y)*(post[i].y - house[j].y));
vector<int> v;
for (int i = 1; i <= n; i++) {
dist[i] = INF;
}
dfs(1, 0, 0, v);
sort(vet.begin(), vet.end());
for (int i=0; i < vet.size();i++) {
cout << vet[i] << ' ';
}
cout << endl;
system("pause");
return 0;
}```