解题报告:POJ2573 Bridge(分析建模)
原题链接:POJ2573
解析:本题没有已知算法模板,需要自己建模。如果想在最短时间内过河,势必要考虑速度最慢的人如何过河,那就需要让速度最快的帮助速度最慢的渡河,这样才可以节约时间。这样问题就可以转化成如何让最慢的人过河才节约时间。设最快的人为a,次快为b,最慢为d,次慢为c,(a<b<c<d)。有两种方案渡河:
- a和b先过河,时间为b,a回来,时间为a,c和d渡河,时间为d,b回来,时间为b,这样c和d就成功渡河,所用时间为b+a+d+b = 2*b+a+d;
- a和c(或d)先渡河,时间为c,a回来,时间为a,a和d渡河,时间为d,a回来,时间为a,c和d成功渡河,时间为c+a+d+a = 2*a+c+d;
错误报告:
- 只考虑到第一种情况,以为这就最优方案,思路也没有明确转化成如何让最慢的人渡河,只是简单的自以为找到规律开始做题。
- 没有考虑到n = 1时情况,此时只需要让这一个人渡河就行了。
- 过于依赖STL,以至于使用优先队列弄巧成拙。
代码实例:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[11111];
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i++) cin >> a[i];
if(n == 1){
cout << a[0] << endl << a[0] <<endl;
return 0;
}
sort(a,a+n);
int nn = n;
int sum = 0;
while(n > 3){
if(2*a[0] + a[n-2]+a[n-1] < 2*a[1]+a[0]+a[n-1]){
sum += 2*a[0] + a[n-2]+a[n-1];
}else{
sum += 2*a[1]+a[0]+a[n-1];
}
n -= 2;
}
if(n == 2) sum += a[1];
else sum += a[2]+a[0]+a[1];
cout << sum << endl;
n = nn;
while(n > 3){
if(2*a[0] + a[n-2]+a[n-1] < 2*a[1]+a[0]+a[n-1]){
printf("%d %d\n%d\n%d %d\n%d\n",a[0],a[n-2],a[0],a[0],a[n-1],a[0]);
}else{
printf("%d %d\n%d\n%d %d\n%d\n",a[0],a[1],a[0],a[n-1],a[n-2],a[1]);
}
n -= 2;
}
if(n == 2) printf("%d %d\n",a[0],a[1]);
else printf("%d %d\n%d\n%d %d\n",a[0],a[2],a[0],a[0],a[1]);
return 0;
}
《算法设计编程实验》——吴永辉P3