HNU 13073 Ternarian Weights 解题报告
本题大意:
用天平对一物品进行称重,现有重量不同的砝码,砝码的重量分别为:1,3,9,27,..,3^n。(n<20)
天平的右侧放砝码,左侧放物品或物品和砝码,使得左右两边的重量相等。
现有一个物品,计算左右两边应当分别放多少个多大的砝码才能使得天平平衡。
例如:现在有一个重量为21的物品,当左侧放物品和重量为9的砝码,右边放重量为27和3的砝码时,天平平衡。
Sample Input |
4 2 3 21 250 |
Sample Output |
left pan: 1 right pan: 3 left pan: right pan: 3 left pan: 9 right pan: 27 3 left pan: 3 right pan: 243 9 1 |
解题思路:
1、首先计算3^i(0<=i<20),然后将计算结果保存至数组st[],数组add[i]=st[0]+st[1]+st[2]+..+st[i]。
2、创建两个数组,left[]保存左侧需要添加的砝码,right[]保存右侧需要删除得砝码。
3、获得大于物品重量的最小add[i]。这是右侧需要的最多得砝码数。
4、计算右侧砝码数与物品重量之差。并找出小于重量之差的最大砝码。
5、如果天平右侧已经没有上一步找出的最大砝码,则在天平的左侧添加此砝码,否则,删除天平右侧中上一步找出得最大砝码。
6、此时,如果天平平衡则退出,若不平衡,则将天平两端的重量之差减去上一步添加或删除的砝码。然后返回第4步。
具体代码如下:
#include <stdio.h> #include <string.h> #define MAX 1000000009 //st[i]=3^i, add[i]=st[0]+st[1]++st[i]; long st[20], add[20]; void init() { int i; st[0] = 1; add[0] = 1; for(i=1; i<20; i++) { st[i] = st[i-1]*3; add[i] = add[i-1]+st[i]; } } int find(int v) //在st数组中,找出小于V的最大数 { int i; for(i=0; i<20; i++) if(v < st[i]) return i-1; } int main() { int n, i, hel, tmp, num, num1, num2; long left[20],right[20]; long w; init(); scanf("%d",&n); while(n--) { memset(left,0,sizeof(left)); memset(right, 0, sizeof(right)); scanf("%ld",&w); for(i=0; i<20; i++) { if(w < add[i]) break; } num = i; num1=0; //左边砝码得个数 num2=i; //右边砝码得个数 hel = add[i]-w; while(hel != 0) //hel==0时, 两端平衡 { //if(hel == 1) //break; tmp = find(hel); //找出小于hel的最大砝码 if(right[tmp] != 0) //右边已删除此砝码 { left[tmp] = st[tmp]; hel = hel-left[tmp]; num1++; } else { right[tmp] = st[tmp]; hel = hel-right[tmp]; num2--; } } // if(hel == 1 && right[0]) // if(hel != 0) // { // left[0] = hel; // } printf("left pan:"); for(i=num; i>=0; i--) { if(left[i] != 0) printf(" %ld",left[i]); } printf("\nright pan:"); for(i=num; i>=0; i--) { if(right[i] == 0) printf(" %ld",st[i]); } printf("\n\n"); } return 0; }