题目链接在这:https://www.luogu.org/problemnew/show/P1094
题目很简单,算法也很简单,我相信没有人不会做这个题的,但是我为什么要写这篇题解呢,因为我被一个东西坑了将近一个小时(我太蒻了!)。
看了好多题解都是用两个指针一个开头一个结尾然后移动,但是我确实一开始就不是这样想的啊!(我蒻!)
先说思路:sort是肯定要sort的,然后直接for一遍每一个物品,用vis数组记录每一件物品有没有被访问过,然后就二分查找w-wi,(问题来了!一开始用的是lower_bound,不知道当时怎么想的,可能是我以前lower_bound用的比较多吧,lower_bound是查找数组中第一个x的位置,这与题目解法肯定大相径庭了),二分查找就用STL的upper_bound,但是问题又来了,upper_bound返回的是位置的后一个位置,所以upper_bound(v.begion,v.end(),x)-v.begin-1才可以找到最后一个x的位置。 每次从w-wi的最后一个位置往前找,并将找到的用vis标记。 这个题目大概就这个一回事。
下面是代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 31000;
bool vis[maxn];
void init()
{
memset(vis,0,sizeof(vis));
}
int main()
{
int w;
while(cin>>w)
{
init();
vector<int> v;
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int tmp;
cin>>tmp;
v.push_back(tmp);
}
sort(v.begin(),v.end());
int cnt = 0;
for(int k=0;k<v.size();k++)
{
if(!vis[k])
{
vis[k] = 1;
bool found = false;
int t = w-v[k];
int pos = upper_bound(v.begin(),v.end(),t)-v.begin()-1;
if(pos==0)
{
cnt++;
continue;
}
for(int i=pos;i>=k;i--)
{
if(!vis[i])
{
vis[i] = 1;
cnt++;
found = true;
break;
}
}
if(!found)
{
cnt++;
}
}
}
cout<<cnt<<endl;
}
return 0;
}
PS:今天水了一篇题解,真开心。