有N个钓鱼点和3个大门。在每个门口都有一些渔民在等待到达最近的无人渔场。 (渔民总数<=N)
连续点之间的距离 = 门和最近点之间的距离 = 1 m
一次只能打开一个门,并且该门的所有渔民必须在下一门打开之前占据位置。
距离计算为到最近点的门 + 最近点到最近的空位。
求所有渔民需要步行的最小距离的总和。
要采取的输入:
钓鱼点数
大门的位置
每个门的渔民人数
按照这个例子:
钓鱼点总数= 10
5 位渔夫在位于位置 4 的 1 号门,
位于位置 6 的 2 号门的 2 名渔民,
3 号门的 2 名渔民位于位置 10,
如果门按顺序打开 G1->G2->G3
安排将是:
距离计算为到最近点的门 + 最近点到最近的空位。
G1闸门打开后,渔民被放置在标有1的位置。
距离 = 11m
G2门打开后,渔民被放置在标有2的位置。
距离 = 5m
G3闸门打开后,渔民被放置在标有3的位置。
距离 = 3m
按此顺序的总距离:11 + 5 + 3 = 19
如果门按顺序打开 G2->G1->G3
案例 1 – 2 号门的最后一个渔夫被放置在位置 7
最后的安排是:
G2门打开后,渔民被放置在标有2的位置。
距离 = 3m
G1闸门打开后,渔民被放置在标有1的位置。
距离 = 12m
G3闸门打开后,渔民被放置在标有3的位置。
距离 = 3m
按此顺序的总距离:3+12+3 = 18
案例 2 – 2 号门的最后一个渔夫被放置在位置 5
最后的安排是:
G2门打开后,渔民被放置在标有2的位置。
距离 = 3m
G1闸门打开后,渔民被放置在标有1的位置。
距离 = 14m
G3闸门打开后,渔民被放置在标有3的位置。
距离 = 3m
此顺序的总距离:3+14+3 = 20
其他情况是多余的
所以最小距离是 18
解决方案:
生成所有组合并在所有门组合中分配渔民以计算最小步行距离。
生成组合可以以递归和迭代方式完成。现在为了消除不必要的排列,我们可以得出结论,对于最短的步行距离,来自特定门的渔民必须呆在一起,即他们应该占据连续的钓鱼点。因此,我们可以将问题想象为 3 个块(渔夫组)在整个钓鱼范围内滑动。其中的最小值是答案。
C++
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
#define MAX 3
int fishspot[100]; // fishing spots
int gate[MAX]; // position of gates
int fishermen[MAX]; // no of fishermen at each gate
int N; // total no of fishing spots
int visited[MAX]; // occupied fishing spots
int Answer; // result
// To unmark spots occupied by fishermen of gate# index
class GFG
{
public :
void reset_fishspot(int index)
{
int i;
for (i = 1; i <= N; i++)
if (fishspot[i] == index + 1)
fishspot[i] = 0;
}
// Calculate minimum distance while
// allotting spots to fishermen of gate# index.
// Returns number of positions possible
// with minimum distance.
// pos1, pos2 is used to return positions
int calculate_distance(int index, int*pos1,
int *pos2, int *score)
{
int i, sum = 0, left_min = 999999,
right_min = 999999,
left, right, npos = 0;
*pos1 = *pos2 = *score = 0;
left = right = gate[index];
// Allot spots to all fishermen except
// last based on minimum distance
for (i = 1; i < fishermen[index]; i++)
{
if (fishspot[gate[index]] == 0)
{
sum++;
fishspot[gate[index]] = index + 1;
}
else
{
left_min = right_min = 999999;
while ((left > 0) && (fishspot[left] > 0))
left--;
while ((right <= N) &&
(fishspot[right] > 0))
right++;
if ((left > 0) && (fishspot[left] == 0))
left_min = gate[index] - left + 1;
if ((right <= N) && (fishspot[right] == 0))
right_min = right - gate[index] + 1;
if (right_min == left_min)
{
// Place 2 fishermen, if available
if ((fishermen[index] - i - 1) > 1)
{
fishspot[left] = fishspot[right] = index + 1;
sum += (2 * left_min);
i++;
// If all fishermen are alloted spots
if (i == fishermen[index])
{
npos = 1;
*score = sum;
return npos;
}
}
else
{
sum += left_min;
fishspot[left] = index + 1;
}
}
else if (left_min < right_min)
{
sum += left_min;
fishspot[left] = index + 1;
}
else if (right_min < left_min)
{
sum += right_min;
fishspot[right] = index + 1;
}
}
}
left_min = right_min = 99999;
// Allot spot to last fishermen
while ((left > 0) && (fishspot[left] > 0))
left--;
if ((left > 0) && (fishspot[left] == 0))
left_min = gate[index] - left + 1;
while ((right <= N) && (fishspot[right] > 0))
right++;
if ((right <= N) && (fishspot[right] == 0))
right_min = right - gate[index] + 1;
if ((sum + left_min) == (sum + right_min))
{
npos = 2;
*pos1 = left;
*pos2 = right;
*score = sum + left_min;
}
else if ((sum + left_min) >
(sum + right_min))
{
npos = 1;
*score = sum + right_min;
fishspot[right] = index + 1;
}
else if ((sum + left_min) <
(sum + right_min))
{
npos = 1;
*score = sum + left_min;
fishspot[left] = index + 1;
}
return npos;
}
// Solve is used to select next gate
// and generate all combinations.
void solve(int index, int sum, int count)
{
int npos, pos1, pos2, score, i;
visited[index] = 1;
if (sum > Answer)
return;
npos = calculate_distance(index, &pos1,
&pos2, &score);
sum += score;
if (count == MAX)
{
if (Answer > sum)
Answer = sum;
return;
}
if (npos == 1)
{
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
}
else if (npos == 2)
{
fishspot[pos1] = index + 1;
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
fishspot[pos1] = 0;
fishspot[pos2] = index + 1;
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
fishspot[pos2] = 0;
}
}
};
// Driver Code
int main()
{
GFG g;
int i;
/*scanf("%d", &N); // for input
for (i = 0; i < MAX; i++)
{
scanf("%d %d", &gate[i], &fishermen[i]);
visited[i] = 0;
}*/
N = 10; // total no of fishing spots
// position of gates(1-based indexing)
gate[0] = 4;
gate[1] = 6;
gate[2] = 10;
//no of fishermen at each gate
fishermen[0] = 5; //gate1
fishermen[1] = 2; //gate 2
fishermen[2] = 2; //gate 3
for (i = 1; i <= N; i++)
fishspot[i] = 0;
Answer = 999999;
for (i = 0; i < MAX; i++)
{
g.solve(i, 0, 1);
visited[i] = 0;
g.reset_fishspot(i);
}
cout << Answer << endl;
return 0;
}
// This code is contributed by SoM15242
C
#define _CRT_SECURE_NO_WARNINGS
#include
#define MAX 3
int fishspot[100]; // fishing spots
int gate[MAX]; // position of gates
int fishermen[MAX]; // no of fishermen at each gate
int N; // total no of fishing spots
int visited[MAX]; // occupied fishing spots
int Answer; // result
//To unmark spots occupied by fishermen of gate# index
void reset_fishspot(int index)
{
int i;
for (i = 1; i <= N; i++)
if (fishspot[i] == index + 1)
fishspot[i] = 0;
}
// Calculate minimum distance while allotting spots to
// fishermen of gate# index.
// Returns number of positions possible with minimum distance.
// pos1, pos2 is used to return positions
int calculate_distance(int index, int*pos1, int *pos2, int *score)
{
int i, sum = 0, left_min = 999999, right_min = 999999,
left, right, npos = 0;
*pos1 = *pos2 = *score = 0;
left = right = gate[index];
// Allot spots to all fishermen except last based on
// minimum distance
for (i = 1; i < fishermen[index]; i++)
{
if (fishspot[gate[index]] == 0)
{
sum++;
fishspot[gate[index]] = index + 1;
}
else
{
left_min = right_min = 999999;
while ((left > 0) && (fishspot[left] > 0))
left--;
while ((right <= N) && (fishspot[right] > 0))
right++;
if ((left > 0) && (fishspot[left] == 0))
left_min = gate[index] - left + 1;
if ((right <= N) && (fishspot[right] == 0))
right_min = right - gate[index] + 1;
if (right_min == left_min)
{
// Place 2 fishermen, if available
if ((fishermen[index] - i - 1) > 1)
{
fishspot[left] = fishspot[right] = index + 1;
sum += (2 * left_min);
i++;
// If all fishermen are alloted spots
if (i == fishermen[index])
{
npos = 1;
*score = sum;
return npos;
}
}
else
{
sum += left_min;
fishspot[left] = index + 1;
}
}
else if (left_min < right_min)
{
sum += left_min;
fishspot[left] = index + 1;
}
else if (right_min < left_min)
{
sum += right_min;
fishspot[right] = index + 1;
}
}
}
left_min = right_min = 99999;
// Allot spot to last fishermen
while ((left > 0) && (fishspot[left] > 0))
left--;
if ((left > 0) && (fishspot[left] == 0))
left_min = gate[index] - left + 1;
while ((right <= N) && (fishspot[right] > 0))
right++;
if ((right <= N) && (fishspot[right] == 0))
right_min = right - gate[index] + 1;
if ((sum + left_min) == (sum + right_min))
{
npos = 2;
*pos1 = left;
*pos2 = right;
*score = sum + left_min;
}
else if ((sum + left_min) > (sum + right_min))
{
npos = 1;
*score = sum + right_min;
fishspot[right] = index + 1;
}
else if ((sum + left_min) < (sum + right_min))
{
npos = 1;
*score = sum + left_min;
fishspot[left] = index + 1;
}
return npos;
}
// Solve is used to select next gate and generate all combinations.
void solve(int index, int sum, int count)
{
int npos, pos1, pos2, score, i;
visited[index] = 1;
if (sum > Answer)
return;
npos = calculate_distance(index, &pos1, &pos2, &score);
sum += score;
if (count == MAX)
{
if (Answer > sum)
Answer = sum;
return;
}
if (npos == 1)
{
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
}
else if (npos == 2)
{
fishspot[pos1] = index + 1;
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
fishspot[pos1] = 0;
fishspot[pos2] = index + 1;
for (i = 0; i < MAX; i++)
{
if (visited[i] == 0)
{
solve(i, sum, count + 1);
visited[i] = 0;
reset_fishspot(i);
}
}
fishspot[pos2] = 0;
}
}
int main()// driver function
{
int i;
/*scanf("%d", &N); // for input
for (i = 0; i < MAX; i++)
{
scanf("%d %d", &gate[i], &fishermen[i]);
visited[i] = 0;
}*/
N=10; // total no of fishing spots
//position of gates(1-based indexing)
gate[0]=4;
gate[1]=6;
gate[2]=10;
//no of fishermen at each gate
fishermen[0]=5; //gate1
fishermen[1]=2; //gate 2
fishermen[2]=2; //gate 3
for (i = 1; i <= N; i++)
fishspot[i] = 0;
Answer = 999999;
for (i = 0; i < MAX; i++)
{
solve(i, 0, 1);
visited[i] = 0;
reset_fishspot(i);
}
printf("%d\n", Answer);
return 0;
}
输出:
18