670 - The dog task
Bob喜歡跟他的狗一起散步,但狗狗跑得比較快,所以狗狗會在散步的過程中跑到其他有趣的地方,只要在每個會合點跟Bob相遇就好了。狗狗的速度是Bob的兩倍,而在兩個會合點之間狗狗頂多只能去一個有趣的地方。
輸入的第一行是有幾筆資料,每筆開頭給兩個數字(<=100),第一個n是Bob會經過多少個會合點,第二個m是地圖上有多少有趣的地方。
接下來第一行是每個會合點的座標,下一行是有趣的點的座標。(最標是絕對值<=1000的int)
輸出先輸出狗狗總共會經過幾個點(會合點+有趣的點),下一行是照順序印出他經過的座標。這個題目可能有多種答案,每一種都可以。
Sample Input
1 4 5 1 4 5 7 5 2 -2 4 -4 -2 3 9 1 2 -1 3 8 -3
Sample Output
6 1 4 3 9 5 7 5 2 1 2 -2 4
想法
簡單的說就是個二分匹配的題目,每個會合點配對一個有趣點(記得最後一個沒有)。
其實題目根本沒什麼,但卻WA了好幾次......
最後發現的問題真的很令人困惑,竟然是出在比較距離的地方,我一開始沒有開根號。
像這樣:
int dis(int a,int b,int c,int d){
int xx=x[a][b]-x[c][d];
int yy=y[a][b]-y[c][d];
return xx*xx+yy*yy;
}
結果加了sqrt後就AC了.....但是這根本不合理啊啊啊!直接用平方比較應該比浮點運算更沒有誤差,而且題目的座標在1000以內,應該也不會有overflow的問題才對啊!
總之是謎啊......
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int n,m,x[2][110],y[2][110];
bool select[110];
int match[2][110]={0};
double dis(int a,int b,int c,int d){
int xx=x[a][b]-x[c][d];
int yy=y[a][b]-y[c][d];
return sqrt(xx*xx+yy*yy);
}
bool reach(int a,int b)
{
if(2*dis(0,a+1,0,a)>=dis(1,b,0,a)+dis(0,a+1,1,b))return true;
else return false;
}
bool find(int no)
{
int i;
for(i=1;i<=m;i++){
if(select[i])continue;
if(!reach(no,i))continue;
select[i]=true;
if(match[1][i]==0){
match[0][no]=i; match[1][i]=no;
return true;
}
else {
if(find(match[1][i])){
match[0][no]=i; match[1][i]=no;
return true;
}
}
}
return false;
}
int main()
{
int N,t,ans,i,j;
scanf("%d",&N);
for(t=1;t<=N;t++){
scanf("%d %d",&n,&m);
memset(match,0,sizeof(match));
ans=0;
for(i=1;i<=n;i++){
scanf("%d %d",&x[0][i],&y[0][i]);
}
for(i=1;i<=m;i++){
scanf("%d %d",&x[1][i],&y[1][i]);
}
for(j=1;j<n;j++){
memset(select,false,sizeof(select));
if(find(j)){
ans++;
}
}
printf("%d\n",n+ans);
for(i=1;i<=n;i++){
printf("%d %d",x[0][i],y[0][i]);
if(match[0][i]!=0){
printf(" %d %d",x[1][match[0][i]],y[1][match[0][i]]);
}
if(i!=n)printf(" ");
}
printf("\n");
if(t<N)printf("\n");
}
return 0;
}
沒有留言:
張貼留言