Regret for being greedy - problem solving report

Regret on being greedy_Elicsyd's blog-CSDN blog

It feels like ordinary greed is that every dimension is equal and there is no priority. Regretful greed means that there is a certain dimension that is immutable and cannot be maintained directly by sorting or heaping. It often needs some processing to dig out the special properties of the immutable dimension in the question so that it can be maintained by sorting or heaping. Wait for the data structure to be greedy.

You can regret greedy common heap (priority_queue) for maintenance.

[E. Buy Low Sell High](Problem - E - Codeforces)

Problem Description:

You can perfectly predict the price of a stock N days in the future. You want to profit from this knowledge, but you only want to trade one stock per day. That is, every day you either buy one share, sell one share, or do nothing. You initially own zero shares, and you can't sell shares when you have no shares. At the end of N days, you want to own fractional shares again, but as much money as possible. — plugin cf better translation

Idea: This question is similar to stock trading, but this allows you to buy/sell/no operation every time, and there is no limit on the number of times you can buy and sell stocks. Direct greedy: buy on day i and sell on day j. It is required that day j is the largest for i, but there is no limit on the number of times. In this way, greed needs to be maintained within the interval, and dp may be needed.

Why do I regret this question: The price abc a < bis for greed to sell, but after selling, it is found at c, a < b < cthat is, |c - a|is greater than |b - a|. At this time, we will find that our greed is wrong, and we should sell again at c. It is found b - a + c - b == c - athat the local optimum can be transformed into the global optimum by using the difference.

Specific code idea: Use a small top pile to maintain the previous minimum value. When the current value is greater than the previous minimum value, you can sell it. After pop, push the current value to the small top pile. Then push the current value into the small top pile, indicating the stock low with the current value as the buying point.

For 1 4 10 20example, the answer is 25, that's 1 --> 10 4 --> 20 或者 1 --> 20 4 --> 10it.

Code:

void solve() {
    
    
    int n; cin>>n;
    vector<int> a(n);
    for(auto &t: a) cin>>t;
    priority_queue<int, vector<int>, greater<int>> q;
    LL ans = 0;
    for(auto t: a) {
    
    
        if(q.size() && q.top() < t) {
    
    
            ans += t - q.top();
            q.pop();
            q.push(t);
        }
        q.push(t);
    }
    cout<<ans<<endl;
}

[P8769 [Lanqiao Cup 2021 National C] Chocolate]([P8769 Lanqiao Cup 2021 National C] Chocolate - Luogu | New Ecosystem of Computer Science Education (luogu.com.cn) )

Problem Description:

Xiao Lan likes chocolate very much. He eats a piece of chocolate every day.

One day Xiaolan went to the supermarket and wanted to buy some chocolates. There are many kinds of chocolates on supermarket shelves. Each chocolate has its own price, quantity and remaining shelf life days. Xiao Lan only eats chocolates that have not passed the shelf life. What is the minimum cost for Xiao Lan to buy one that can last for x days? chocolate.

Idea: This question is similar to the previous one. Sort abc by b, and start regret greedy by b from big to small (from big to small if regret is simple and must be possible). The difference from the previous question is that this question also has a quantity c, but the previous question does not. It can be found that only x pieces of bread are needed to meet the conditions, and for day i, as long as the shelf life of the bread is greater than or equal to i, just choose the one with the smallest price without any thought. Therefore, the simulation can be carried out based on the number of days from the end day to the start day, and each time the bread with the minimum price that has not expired is found.

Specific code idea: Use array<int,3> to save in sequence a b c, and sort by b from large to small. Use a custom small top heap to maintain the minimum price of the remaining bread that satisfies bread and does not expire after traversing to i. Just find a minimum price and add it to the answer each time.

Code:

void solve() {
    
    
	int n,x; cin>>x>>n;
	vector<array<int,3>> va(n);
	for(auto &t:va) cin>>t[0]>>t[1]>>t[2]; // a b c
	sort(all(va), [](array<int,3> pre, array<int,3> suf) {
    
    
		return pre[1] > suf[1];
	});
	auto cmp = [](PII pre, PII suf) {
    
    
		return pre.vf > suf.vf;
	};
	priority_queue<PII, vector<PII>, decltype(cmp)> maq(cmp);
	LL ans = 0;
	int pos = 0;
	for(int i = x; i >= 1; --i) {
    
    
		while(pos < n && va[pos][1] >= i) {
    
    
			maq.push({
    
    va[pos][0], va[pos][2]});
			pos++;
		}
		if(maq.size() == 0) {
    
    
			cout<<-1;
			return ;
		}
		auto tmp = maq.top(); maq.pop();
		ans += tmp.vf; tmp.vs--;
		if(tmp.vs != 0) {
    
    
			maq.push({
    
    tmp});
		}
	}
	cout<<ans;
}

[P4053 [JSOI2007] Building emergency repair]([P4053 JSOI2007] Building emergency repair - Luogu | New ecology of computer science education (luogu.com.cn) )

Problem Description:

Xiaogang is playing a computer game called "Building Repair" provided by JSOI: After a fierce battle, the T tribe eliminated all the Z tribe's invaders. However, � N been seriously damaged. If they are not repaired as soon as possible, these buildings and facilities will be completely destroyed. The current situation is: There is only one repairman in the T tribe base. Although he can reach any building instantly, it will take a certain amount of time to repair each building. At the same time, repair workers can only repair the next building after repairing one building, and cannot repair multiple buildings at the same time. If a building is not fully repaired within a period of time, the building is scrapped. Your task is to help Xiaogang formulate a reasonable repair sequence to repair as many buildings as possible.

Idea: Each building has a final deadline and repair time. Sort the deadlines from small to large (the principle is the same as above) and use a variable to record the current time. If the current time plus the maintenance time is within the deadline, it is OK. Otherwise, find the most time-consuming building among the previous buildings. If If the best one is greater than the current time consumption, replace it, squeeze out some time, and increase the chance of success for subsequent operations.

Specific code idea: Use pair to store maintenance time and deadline. Sort by deadline in ascending order. Use a variable lasttmto record the current time. If lasttm + vf <= vsit means that the building can be repaired successfully before the deadline, it will be updated lasttm, and the maintenance time vfwill be put into the big pile; if the requirements are not met, it means that the building cannot be repaired successfully before the deadline. time before, then one of the previously repaired buildings with a longer repair time will be replaced with this one, and the lasttmnumber of updates must be smaller lasttmthan the previous one that has not been updated .lasttm

Code:

void solve() {
    
    
    int n; cin>>n;
    vector<PII> vp(n);
    for(auto &t: vp) cin>>t.vf>>t.vs;
    sort(all(vp), [&](PII pre, PII suf) {
    
    
        return pre.vs < suf.vs;
    });
    int cnt = 0;
    int lasttm = 0;
    priority_queue<int> pq;
    for(int i = 0; i < n; ++i) {
    
    
        if(lasttm + vp[i].vf <= vp[i].vs) {
    
    
            cnt++;
            lasttm += vp[i].vf;
            pq.push(vp[i].vf);
        } else if(pq.top() > vp[i].vf) {
    
    
            lasttm -= pq.top(); pq.pop();
            lasttm += vp[i].vf; pq.push(vp[i].vf);
        }
    }
    cout<<cnt;
}

[tokitsukaze and Soldier](tokitsukaze and Soldier (nowcoder.com))

Problem Description:

Link: https://ac.nowcoder.com/acm/problem/50439
Source: Niuke.com

In a game, Tokitsukaze needs to select some soldiers from n soldiers to form a regiment to fight the dungeon.
The combat strength of the i-th soldier is v[i], and the combat strength of the regiment is the sum of the combat strengths of all soldiers in the regiment.
But these soldiers have special requirements: if the i-th soldier is selected, this soldier hopes that the number of people in the regiment will not exceed s[i]. (If you do not select the i-th soldier, there is no such restriction.)
Tokitsukaze wants to know what the maximum combat strength of the regiment is.

Idea: Sort in descending order according to the number of people not exceeding the special requirements, because if the number of people required drops, the soldiers who entered before can be removed from the team without thinking about other information.

Specific code idea: Use pairs to store combat power and the number of people required in sequence, and sort by the number of people required in descending order. Use a small top pile to maintain the combat power of soldiers who meet the required number limit. For the i-th soldier, enter the answer++, and then process the number limit that meets the current soldier requirements. If there are excess, the one with the lowest combat strength will be removed from the team. Max is taken every time when traversing the soldiers (because the intermediate requirement may be the sum of the maximum combat power, but the record is the sum of the maximum combat power when the last soldier is traversed.

Code:

void solve() {
    
    
    int n; cin>>n;
    vector<PII> vp(n);
    for(auto &t: vp) cin>>t.vf>>t.vs; // v s1
    sort(all(vp), [](PII pre, PII suf) {
    
    
        return pre.vs > suf.vs;
    });
    LL ans = 0;
    LL ma = -3;
    priority_queue<int,vector<int>,greater<int>> pq;
    for(auto t: vp) {
    
    
        ans += t.vf;
        pq.push(t.vf);
        while(pq.size() > t.vs) {
    
    
            ans -= pq.top(); pq.pop();
        }
        ma = max(ma, ans);
    }
    cout<<ma;
}

Summarize

But regretful greed feels that sorting and heaping perfectly utilize the properties in the question and solve the shortcomings of ordinary greed.

Found it to be greed--> Conventional greed is a bit strange--> Consider regretting greed/change the method/struggle again--> Others

Guess you like

Origin blog.csdn.net/qq_63432403/article/details/132651726