這件事情的起因是在學習背包問題時突然想到了一種算法,分析了一下應該是n^2logn復雜度的,當然比dp慢。但是既然想到了就實現了下:
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ll; /*一個很低效的方法,但是是自己想到的,就順手實現了一下。本質是基於窮舉法的優化,不再循環所有物品選取的組合,而是循環狀態。 大致地看,其一定是比窮舉法要快些的,因為其合並了窮舉法的許多情況,即處於“現在背包中物品的總價值相同且剩余空間相同”的不同物品選取情況。 但是其的復雜度至少是n^2*logn級別的,因為其需要對每一個物品循環set中的元素並不斷插入新的狀態,而且還涉及到了類的存儲,速度應該會更慢一些 */ class stateNow{ public: int sizeRest; int valueAll; bool operator <(const stateNow& te)const{ if((this->sizeRest<te.sizeRest)||(this->sizeRest==te.sizeRest&&this->valueAll>te.valueAll)) return true; else return false; } }; int main(){ int n,size; scanf("%d %d",&n,&size); int *objectSize=new int[n]; int *objectValue=new int[n]; set<stateNow>::iterator it; set<stateNow>stateCollection; int maxValue=0; for(int i=0;i<n;i++){ scanf("%d %d",&objectSize[i],&objectValue[i]);//不能把\n也加到字符串里,\n是輸入結束的標志,將它也讀入的話會影響結束 } for(int i=0;i<n;i++){ if(!stateCollection.empty()){ for(it=stateCollection.begin();it!=stateCollection.end();it++){ stateNow temp; temp.sizeRest=it->sizeRest-objectSize[i]; temp.valueAll=objectValue[i]+it->valueAll; if(temp.sizeRest==0){ if(temp.valueAll>maxValue) maxValue=temp.valueAll; } if(temp.sizeRest>0) stateCollection.insert(temp); } } stateNow temp; temp.sizeRest=size-objectSize[i]; temp.valueAll=objectValue[i]; stateCollection.insert(temp); } printf("%d",maxValue); getchar(); } }
這里就涉及到了一個向set中傳入自定義類型的問題,查到了一篇博文,正好在講這個問題,這里就不引用原文了,大家直接點擊鏈接看吧:https://www.cnblogs.com/shawnhue/archive/2011/12/22/set_comparison_strick_weak_ordering.html
為什么需要定義比較函數對象或者自定義<運算符呢?因為set內部是有序排列的(紅黑樹),並且要保證元素的唯一性,所以需要一個能用來比較兩元素的方法。(two keys k1 and k2 are considered to be equivalent if for the comparison object comp, comp(k1, k2) == false && comp(k2, k1) == false.)
另外,由博文中所說,總是讓比較函數使被比較對象滿足嚴格的弱序,即
嚴格弱序化擁有如下屬性。對於集合S中所有的x,y,z,
對於所有的x,不存在x < x (非自反性 - 21條標題說的就是這個)
對於所有x不等於y,如果x < y那么不存在y < x (不對稱性)
對於所有的x,y和z,如果x < y並且y < z,那么x < z(傳遞性)
如果x < y,那么對於所有的z,要么x < z要么z < y(或者兩者都成立)
這一點在自定義<運算符時要注意,否則所進行的操作就是未定義行為,會出現意料之外的錯誤。