被贪心和分治又虐了一天,还是太弱了..
题目是这样的:有这样一个奇怪的天平,它的砝码只有1g, 3g, 9g, 27g......并且各只有一个,但它却能够称出所有整数g质量的物体例如要称出质量2g,那就一边放一个3g,另一边放物体和1g的砝码就可以了。放在物体那边的砝码在前面加负号表示之。
有候选集合,需要求近似解或者最优解,这基本是贪心分治的标配,而核心思想就是根据候选集合不断的迭代问题的规模使其缩小,代码如下:
1 #include "stdafx.h" 2 #include<cstdlib> 3 #include <stdio.h> 4 #define Max 21 5 //构造候选集合,自己做的时候已经被提示是贪心应用了,居然还是自己傻傻的算呢...真是天真 6 unsigned int Data[Max]={1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969,14348907, 7 43046721,129140163,387420489,1162261467,3486784401 }; 8 //二分查找,确定子问题的解,当然这次用到了指针,虽然还不清楚指针有什么优劣,不过这次还是蛮好用的。 9 unsigned int *Binary_Search(unsigned int k) 10 { 11 int left = 0; 12 int right = Max - 1; 13 int middle; 14 while(left <= right) 15 { 16 middle = (left + right) / 2; 17 if(k > Data[middle]) 18 left = middle + 1; 19 else if(k< Data[middle - 1]) 20 right = middle - 1; 21 else 22 if(k >= Data[middle - 1] && k <= Data[middle]) 23 { 24 if( k == Data[middle - 1]) 25 return &Data[middle - 1]; 26 else 27 return &Data[middle]; 28 } 29 } 30 return &Data[middle]; 31 } 32 // 33 int k = -1; 34 int mark = 0; 35 //输入最终解,当然自身也是递归的对象 36 void Print(unsigned int m) 37 { 38 unsigned int *i; 39 i = Binary_Search(m); 40 //迭代的最后一个子问题,输出结束本次运算 41 if(*i == m) 42 { 43 printf("%u",m); 44 return; 45 } 46 //在本题中,一个数如果大于等于3^n的一半,那么它的上界就是3^n,否则就是3^(n - 1),在这里用到了指针代替数组运算 47 if(*i / 2 >=m) 48 i = i -1; 49 //辗转相减,不断的缩小目标值,k值则是加减号的标志(正为加,负为减) 50 if(*i < m) 51 { 52 m = m - *i; 53 k = 1; 54 } 55 //同上 56 else 57 { 58 m = *i -m; 59 } 60 printf("%u",*i); 61 //mark和k是控制辗转相减过程中符号的显示 62 if(mark == 1) 63 k = -k; 64 // 65 if(k == 1) 66 { 67 printf(" + "); 68 mark = 0; 69 k = -1; 70 } 71 // 72 else 73 { 74 printf(" - "); 75 mark = 1; 76 } 77 //递归迭代 78 Print(m); 79 } 80 81 int _tmain(int argc, _TCHAR* argv[]) 82 { 83 unsigned int m; 84 while(scanf("%d",&m) != EOF) 85 { 86 printf("%d = ",m); 87 Print(m); 88 } 89 system("Pause"); 90 return 0; 91 }
总的来说,算是基本掌握了贪心分治的基础应用,这两天没有白虐,在一些细节上还有不熟练的地方,但是总算能给自己打个70分吧。