拼多多笔试货运装箱那一题的贪心策略
贪心策略:
step1:将货物按重量从小到大排序,将重量大于200的直接装箱step2:设置左右两个区间游标left和right,接着考虑到100+200这种临界情形,先将right左移到第一个小于200的下标处,将left右移到第一个大于100的下标处,将left~right区间内的货物首尾匹配,如果<=300就装箱,并mark这两个位置已经访问过,如果大于300就不装箱(right这个位置的货物也不装)将right左移一个位置继续匹配直到left == right
step3:在step2的基础上再将100和200重的货物加进来,并将left置0,right置为最后一个货重<=200的货物下标处,首尾匹配,先检验left和right这两个货物是否已mark过,如果mark了就left++或者right--,若都未被标记,当right处货重为100则直接将区间剩余货物一次性3箱这样带走,当right处货重>100时且和重<=300则将left和right处的货物一块装箱带走同时缩进left和right,>300则只能将right处货物装箱带走并缩进right
tips:比较关键的一个点就是100+200这种临界情况要考虑清楚,还有容易疏忽的就是区间内剩下货物全是100的时候就不能再首尾匹配了而应该3箱3箱这样子装箱带走
ps:有问题的欢迎指正
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 1005; int w[maxn]; bool mark[maxn]; int main(){ int t,n = 0,res = 0; while(~scanf("%d",&t)){ w[n] = t; mark[n++] = false; } sort(w,w+n); int left = 0,right = n - 1; while(right >= 0 && w[right] > 200){ res++; right--; } //保存第一个<=200的元素下标 int nr = right; while(right >= 0 && w[right] == 200){ right--; } while(left < n && w[left] == 100){ left++; } while(left < right){ if(w[left] + w[right] <= 300){ res++; mark[left] = mark[right] = true; left++; right--; }else{ right--; } } right = nr; left = 0; while(left <= right){ if(mark[left]){ left++; }else if(mark[right]){ right--; }else if(left == right){ res++; break; }else if(w[right] == 100){ int len = right - left + 1; res = res + len/3 + (len%3 > 0 ? 1 : 0); break; }else if(w[left] + w[right] <= 300){ res++; left++; right--; }else{ res++; right--; } } printf("%d\n",res); return 0; }
#内推##拼多多##笔试题目#