这题是一个比较简单的贪心题,不过如果不知道的话,可能会很unhappy了,因为这个是逆向来的,也就是如果你知道了用M块木板覆盖的消耗的话,那么你就可以算出用M-1块木板覆盖的最小覆盖,方法就是在M块木板中找相邻的两块木板相差距离最小的,然后把这两块木板连起来,这样的消耗一定是最小的(这个就不用证明了吧,很明显的)。根据这个思路,可以比较容易的A掉这题,但是还有一些实现的细节下面看代码吧。
对于样例的覆盖过程是
[3][4][6][8][14][15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14][15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41,42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6][8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6,8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6,8][14,15,16,17][21][25,26,27,30,31][40,41,42,43]
[3,4,6,8][14,15,16,17,21][25,26,27,30,31][40,41,42,43]
对于样例的覆盖过程是
[3][4][6][8][14][15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14][15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15][16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16][17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25][26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26][27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30][31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40][41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41][42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41,42][43]
[3,4][6][8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6][8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6,8][14,15,16,17][21][25,26,27][30,31][40,41,42,43]
[3,4,6,8][14,15,16,17][21][25,26,27,30,31][40,41,42,43]
[3,4,6,8][14,15,16,17,21][25,26,27,30,31][40,41,42,43]
code
6 #include <iostream>
7 #include <string.h>
8 using namespace std;
9 /**//*结构体村每个点的数据
10 其中data表示输入的数据
11 left和right表示他的左右边
12 有没有连了其他的木板
13 */
14 typedef struct
15 {
16 int data;
17 int left,right;
18 }Node;
19 Node node[202];
20 bool b_barn[202];//b_barn[i]表示第i号牛棚有没有被木板覆盖
21 int m,s,c;//和题目中的一样
22 void work()
23 {
24 int f_start,f_end,dis;//dis表示最小距离
25 //f_start表示最小距离时的左边的下标
26 //f_end 表示最小距离时的右边的下标
27 int count = 0;//用来存最后的结果
28 int t = c;//表示一开始用c块木板,也就是一个牛棚一块
29 dis = 202;//最大距离,表示无穷
30 while(t > m)
31 {
32 dis = 202;
33 for(int i = 1;i < c;i++)//循环数组,找相隔最小的,然后连上
34 {//因为这样“浪费”的木板最少,也就是能达到最优解
35 if(((node[i].data - node[i-1].data) < dis)&&(0 == node[i].left||0 == node[i-1].right))
36 {//第一个判断条件很好理解,第二个是表示他们以前没连过,不然的话,
37 //会一直找到第一个最小的 ,而忽略了后面的
38 dis = node[i].data - node[i-1].data;
39 f_start = i-1;
40 f_end = i;
41 }
42 }
43 for(int i = node[f_start].data+1;i < node[f_end].data;i++)
44 {//将连起来的两块木板中间的都置为被覆盖
45 b_barn[i] = true;
46 }
47 node[f_start].right = 1;//标记,也就是这个点的右边连了其他木板
48 node[f_end].left = 1;//标记,也就是这个点的左边连了其他木板
49 t--;//表示木板数减少1
50 }
51 for(int i = node[0].data;i < node[c-1].data+1;i++)
52 {
53 if(b_barn[i])//通过被标记的数组来算最后的结果
54 count++;
55 }
56 printf("%d\n",count);
57 }
58 int cmp(const void *a,const void *b)
59 {
60 Node * c = (Node *)a;
61 Node * d = (Node *)b;
62 return c->data - d->data;
63 }
64 int main(void)
65 {
66 freopen("barn1.in","r",stdin);
67 freopen("barn1.out","w",stdout);
68 scanf("%d %d %d",&m,&s,&c);
69 memset(b_barn,false,sizeof(b_barn));//初始化数组
70 for(int i = 0;i < c;i++)
71 {
72 scanf("%d",&node[i].data);
73 node[i].left = node[i].right = 0;//初始化所有的都没有连过
74 b_barn[node[i].data] = true;
75
76 }
77 qsort(node,c,sizeof(node[0]),cmp);//先排序,使木板有序
78 work();
79 return 0;
80 }
81
6 #include <iostream>
7 #include <string.h>
8 using namespace std;
9 /**//*结构体村每个点的数据
10 其中data表示输入的数据
11 left和right表示他的左右边
12 有没有连了其他的木板
13 */
14 typedef struct
15 {
16 int data;
17 int left,right;
18 }Node;
19 Node node[202];
20 bool b_barn[202];//b_barn[i]表示第i号牛棚有没有被木板覆盖
21 int m,s,c;//和题目中的一样
22 void work()
23 {
24 int f_start,f_end,dis;//dis表示最小距离
25 //f_start表示最小距离时的左边的下标
26 //f_end 表示最小距离时的右边的下标
27 int count = 0;//用来存最后的结果
28 int t = c;//表示一开始用c块木板,也就是一个牛棚一块
29 dis = 202;//最大距离,表示无穷
30 while(t > m)
31 {
32 dis = 202;
33 for(int i = 1;i < c;i++)//循环数组,找相隔最小的,然后连上
34 {//因为这样“浪费”的木板最少,也就是能达到最优解
35 if(((node[i].data - node[i-1].data) < dis)&&(0 == node[i].left||0 == node[i-1].right))
36 {//第一个判断条件很好理解,第二个是表示他们以前没连过,不然的话,
37 //会一直找到第一个最小的 ,而忽略了后面的
38 dis = node[i].data - node[i-1].data;
39 f_start = i-1;
40 f_end = i;
41 }
42 }
43 for(int i = node[f_start].data+1;i < node[f_end].data;i++)
44 {//将连起来的两块木板中间的都置为被覆盖
45 b_barn[i] = true;
46 }
47 node[f_start].right = 1;//标记,也就是这个点的右边连了其他木板
48 node[f_end].left = 1;//标记,也就是这个点的左边连了其他木板
49 t--;//表示木板数减少1
50 }
51 for(int i = node[0].data;i < node[c-1].data+1;i++)
52 {
53 if(b_barn[i])//通过被标记的数组来算最后的结果
54 count++;
55 }
56 printf("%d\n",count);
57 }
58 int cmp(const void *a,const void *b)
59 {
60 Node * c = (Node *)a;
61 Node * d = (Node *)b;
62 return c->data - d->data;
63 }
64 int main(void)
65 {
66 freopen("barn1.in","r",stdin);
67 freopen("barn1.out","w",stdout);
68 scanf("%d %d %d",&m,&s,&c);
69 memset(b_barn,false,sizeof(b_barn));//初始化数组
70 for(int i = 0;i < c;i++)
71 {
72 scanf("%d",&node[i].data);
73 node[i].left = node[i].right = 0;//初始化所有的都没有连过
74 b_barn[node[i].data] = true;
75
76 }
77 qsort(node,c,sizeof(node[0]),cmp);//先排序,使木板有序
78 work();
79 return 0;
80 }
81