bool Cpn[60000]; // 维护当前每头牛有没有用优惠券 int Usc[60000]; // 用了优惠券的牛 int Duc[60000]; // 没有用优惠券的牛 int n, k; longlong m;
int Ans;
intCalc(){ // 为当前状态估价 int Num[60000]; for(int i = 1; i <= n; i++) Num[i] = Cpn[i] ? s[i].c : s[i].p; sort(Num+1, Num+n+1); int Ans = 0; longlong Res = 0; for(int i = 1; Res <= m && i <= n; i++){ Res += (longlong)Num[i]; Ans++; } if(Res <= m) return Ans; return Ans - 1; }
voidSA(){ for(double Temp = 2000; Temp >= 1; Temp *= 0.9){ // 退火 int x = rand() % k + 1; // 在用了优惠券的牛里面选一头 int y = rand() % (n - k) + 1; // 在没用…… swap(Usc[x], Duc[y]); Cpn[Usc[x]] = true; Cpn[Duc[y]] = false; int Nxt = Calc(); int Del = Nxt - Ans; if(Del > 0) Ans = Nxt; elseif(exp(-(double)Del / Temp) * RAND_MAX * 2 < rand()){ // 有概率接受一个更差解 swap(Usc[x], Duc[y]); Cpn[Usc[x]] = true; Cpn[Duc[y]] = false; } } }