贪心砝码(分治法)

被贪心和分治又虐了一天,还是太弱了..

题目是这样的:有这样一个奇怪的天平,它的砝码只有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分吧。

 

posted on 2013-10-30 23:37  光明小天使  阅读(532)  评论(0编辑  收藏  举报