洛谷 P1094 纪念品分类

刚开始看到这题就确定这题最好先要排序

第一个想法是排好序后先让第一个和从倒数第一个开始相加和如果就  <= w,那么用n除以2或者再加一得出答案,然后发现随便

当w = 110  n = 5序列为 10 50 60 90 100便不成立,遂将其舍弃。

第二个想法:依旧是从前面和倒数往前的相加,如果大于 W,那么就代表这个后面的肯定会自成一组,因为当前面的再进一位,肯定

要比之前的一位还要大,由此得出。

如果前面加后面的和小于W, 那么计数器会+1, 然后前面往后进一位,后面的往前进一位。

只存在①:前面的向后进    后面往前面进

   ②:后面的向前面进 前面不动

而不存在前面的往后面进后面的不动的情况。

需要注意的是:用过的数据需要标记一下,这样能够保证用过的数据不会再被使用,

我是标记从前往后的数据。

所以就由这两种情况得出代码,代码如下:

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 bool vis[30005];
 5 int a[30005];
 6 int main(){
 7     int w, n;
 8     scanf("%d %d",&w,&n);
 9     for(int i = 1 ; i <= n; i ++) scanf("%d",&a[i]);
10     sort(a + 1, a + n + 1);        //先由小到大排好序 
11     int cnt = 0, j = 0;
12     for(int i = 1; i <= n ; i ++){
13         if(vis[n - j] == true){        //判断终止条件        
14             break;
15         }
16         if(a[i] + a[n - j] <= w){    
17             vis[i] = true;        //标记数据 
18             cnt++;
19         }else{
20             i--;            //假如两者和大于W,那么i先减再加固定不动,后面的前进 
21             cnt++;
22         }
23         j++;
24     }
25     printf("%d
",cnt);
26     return 0;
27 } 
原文地址:https://www.cnblogs.com/pureayu/p/12261560.html