今晚CF GYM A题,神坑。。
原题:
Aspen Avenue
``Phew, that was the last one!‘‘ exclaimed the garden helper Tim as he threw the last tree plant to the ground. His employer, countess Esmeralda Hunt who owned the estate, has ordered him to arrange an avenue of aspen trees along both sides of the front road leading up to the house. The first trees in the avenue are supposed to be planted at the very beginning of the road, and the last trees of the avenue at the very end of the road. Tim, who was constantly being reminded of her sense of accuracy, knew that the countess would insist on the trees being placed in perfectly aligned tree pairs, one on each side of the road, and with exactly the same spacing between the pairs along the road. However, when bringing the tree plants to the estate, Tim had just dropped them arbitrarily along the left side of the road and was now facing the task of moving the trees to their correct positions to meet the countess‘s requirements. Being stronger in mind than in arms, and since it was time for a coffee break anyway before he started digging, he sat down to figure out which trees to move to which positions so as to minimize the total (Euclidean) distance that he had to move the trees.
Input
The input file contains several test cases, each of them as described below.
The input starts with a positive even integer N between 4 and 2000 (inclusive), giving the total number of trees in the avenue. The next line contains two integers L and W , where 1L10000 is the length of the road, in meters, and 1W20 is the width of the road, in meters. The next N lines each describe where Tim had dropped of the trees. Each such line contains an integer 0pL indicating the position of a tree plant along the left side of the road, measured in meters from the start of the road.
Output
For each test case, write to the output the smallest total number of meters the tree plants need to be moved, on a line by itself. The answer should be given with an absolute or relative error of at most 10-6 .
Sample Input
4 10 1 1 0 10 10 6 10 1 0 9 3 5 5 6
Sample Output
2.4142135624 9.2853832858
题意:
一条长为L,宽为W的道路,两旁共需要种N棵树。每两棵树作为一对,严格戳在距起点相同距离的道路两旁。每相邻两对树之间的距离要求严格相等。前两棵在0处,最后两棵在L处。
初始时所有树都在道路的左侧乱序散布(输入位置),问最少需要将树总共移动多少欧氏距离才能把他们移动到规定的位置。
思路:
开始会想到sort一下,然后依次让两棵树跑到距起点最近的没有树的位置去,稍微计算一下,能发现将距离规定位置最近的那棵树放在道路左边,将另一棵树放到道路右边是对这两棵树来说最优的。但是连WA 4发以后放弃了。。。
最后确定DP来做,但由于是树形展开(from God crccw),所以直接for是不大行的,用dfs记忆化搜索可以解决。
dp[i][j]=dfs(i,j)=min(dfs(i+1,j)+dis(tree[i+j],左侧i+1位置) ,dfs(i,j+1)+dis(tree[i+j],右侧j+1位置));
tips:dp[i][j]初始化为INF;下标从0开始
代码:
1 #include<stdio.h> 2 #include<math.h> 3 #include<algorithm> 4 using namespace std; 5 6 const double INF = 100000000000; 7 int n; 8 double l,w; 9 double a[3000]; 10 double itv; 11 double dp[3000][3000]; 12 bool fact[3000][3000]; 13 14 void ini() 15 { 16 for(int i=0;i<=n;i++) 17 for(int j=0;j<=n;j++) 18 { 19 dp[i][j]=INF; 20 fact[i][j]=0; 21 } 22 } 23 24 double dfs(int l,int r) 25 { 26 if(l>=n&&r>=n) return 0; 27 if(fact[l][r]) return dp[l][r]; 28 fact[l][r]=1; 29 30 if(l<n) dp[l][r]=min(dfs(l+1,r)+fabs(a[l+r]-l*itv),dp[l][r]); 31 if(r<n) dp[l][r]=min(dfs(l,r+1)+sqrt((a[l+r]-r*itv)*(a[l+r]-r*itv)+w*w),dp[l][r]); 32 33 return dp[l][r]; 34 } 35 36 int main() 37 { 38 scanf("%d",&n); 39 scanf("%lf%lf",&l,&w); 40 for(int i=0;i<n;i++) 41 { 42 scanf("%lf",&a[i]); 43 } 44 ini(); 45 sort(a,a+n); 46 n=n/2; 47 itv=l/((double)n-1); 48 49 printf("%.10f\n",dfs(0,0)); 50 return 0; 51 }
至于开始那种贪心做法为何不对,经过一番多次平方的不等式计算应该可以得到。
题外话:
今天在缺少雷神的极其恶劣的情况下,神队友crccw带着我做了zoj monthly march 2013和CF GYM,GYM是NCPC2008的题目,明明是A题,看起来也不是很难,,WA了5发,看了大牛博客才过。。也是学习了。。。
自己太弱,不过只要脸皮厚,就能继续学习。。多靠神队友。
晚安!