cf1203F(div3)

9 篇文章 0 订阅
8 篇文章 0 订阅

这两题卡我一天, 不过div3不ak说不过去

题意(easy-version):

  • 有i个单位
  • 现有n件物品, 每个物品有两个属性a, b,至少有a个单位才能购置这个件物品, b购置这件物品后你会得到不确定的收益b(b 有可能小于0), 即目前的单位数+b
  • 现在询问你能否购置所有的物品

>> face <<

前置技能: 贪心

原来想先按照物品的前提条件排序, 然后再满足所有前提条件的物品里面选一个收益最高的, 结果当然wa; 这样想仅针对是正数的情况, 对于收益是负数的情况怎么办呢

我们假设有两件商品 x , y x, y x,y, 目前有cur元, 且购置了x后无法购置y , 即:

c u r + x . s e c o n d ≥ y . s e c o n d c u r + y . s e c o n d < x . f i r s t 合 并 之 后 即 为 : x . f i r s t + x . s e c o n d > y . f i r s t + y . s e c o n d cur+x.second\geq y.second\\ cur+y.second <x.first\\ 合并之后即为:\\ x.first + x.second > y.first + y.second cur+x.secondy.secondcur+y.second<x.first:x.first+x.second>y.first+y.second

于是我们就可以按照这个规律排序

#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (int i = (a); i >= (b); --i)
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rof(i, a, b) for (int i = (a); i > (b); --i)
#define oo 0x3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl;
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair<int, int>
int nxt()
{
	int ret;
	scanf("%d", &ret);
	return ret;
}
vector<pii> neg, pos, cppo, cpne;
pii tmp;

int main() {
	int n = nxt(), cur = nxt();
	_rep(i, 1, n) {
		tmp.first = nxt(), tmp.second = nxt();
		if (tmp.second < 0) neg.emplace_back(tmp);
		else pos.emplace_back(tmp);
	}
	sort(all(neg), [](const pii a, const pii b) {return a.first == b.first ? a.second > b.second: a.first < b.first; });
	sort(all(pos), [](const pii a, const pii b) {return a.first == b.first ? a.second > b.second : a.first < b.first; });
	bool okay = 1;

	_rep(i, 1, n) {
		cppo = pos;
		cpne = neg;
		int th = upper_bound(pos.begin(), pos.end(), pii{ cur, -oo }, [](const pii a, const pii b) {return a.first == b.first ? a.second > b.second : a.first < b.first; }) - pos.begin();
		if (th) {//有正数的
			sort(cppo.begin(), cppo.begin() + th, [](const pii a, const pii b) {return a.second > b.second; });
			cur += cppo[0].second;
			pos.erase(find(all(pos), cppo[0]));
		}
		else {
			int th = upper_bound(all(neg), pii{ cur, -oo }, [](const pii a, const pii b) {return a.first == b.first ? a.second > b.second : a.first < b.first; }) - neg.begin();
			if (th == 0) {
				okay = 0;
				break;
			}
			sort(cpne.begin(), cpne.begin() + th, [](const pii a, const pii b) {return a.first + a.second > b.second + b.first; });
			cur += cpne[0].second;
			neg.erase(find(all(neg), cpne[0]));
			if (cur < 0) {
				okay = 0;
				break;
			}
		}
	}
	okay ? cout << "YES" << endl : cout << "NO" << endl;
}

题意(hard-version):

  • 有i个单位
  • 现有n件物品, 每个物品有两个属性a, b,至少有a个单位才能购置这个件物品, b购置这件物品后你会得到不确定的收益b(b 有可能小于0), 即目前的单位数+b
  • 先询问最多能购置多少物品

>> face <<

前置技能: 贪心 + dp

有注意到这题商品数n最多只有100, 而且最大的cur最多也就60000, 完全可以dp来搞

这题我一直写的贪心, 怎么都过不了, 看网上题解写的贪心都是可反悔, 唉, 还是dp算了

状态: d p [ i ] [ j ] dp[i][j] dp[i][j] 代表已经购置了i件物品, 现在还剩j块钱

初始化: d p [ 0 ] [ c u r ] = a n s dp[0][cur] = ans dp[0][cur]=ans: ans是贪到的正收益的物件数,cur是加上正收益后的钱;

转移:

{ d p [ i + 1 ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i + 1 ] [ j ] ) → 不 买 d p [ i + 1 ] [ j + n e g [ i ] . s e c o n d ] = m a x ( d p [ i + 1 ] [ j + n e g [ i ] . s e c o n d ] , d p [ i ] [ j ] + 1 ) → 买 他 \begin{cases} dp[i+1][j] = max(dp[i][j], dp[i+1][j])\to不买 \\ dp[i+1][j+neg[i].second] = max(dp[i+1][j+neg[i].second], dp[i][j]+1)\to 买他 \end{cases} {dp[i+1][j]=max(dp[i][j],dp[i+1][j])dp[i+1][j+neg[i].second]=max(dp[i+1][j+neg[i].second],dp[i][j]+1)

有注意到每个dp[i]只与dp[i-1]有关, 所以还可以用滚动数组优化空间, 但是时间复杂度还是不变的

#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (int i = (a); i >= (b); --i)
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rof(i, a, b) for (int i = (a); i > (b); --i)
#define oo 0x3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl;
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair<int, int>
int nxt()
{
	int ret;
	scanf("%d", &ret);
	return ret;
}
vector<pii> neg, pos, cppo, cpne;
int dp[60000 + 3];
pii tmp;

int main()
{
	int n = nxt(), cur = nxt();
	_rep(i, 1, n)
	{
		tmp.first = nxt(), tmp.second = nxt();
		if (tmp.second < 0)
			neg.emplace_back(tmp);
		else
			pos.emplace_back(tmp);
	}
	sort(all(neg), [](const pii a, const pii b) { return a.first + a.second > b.first + b.second; });
	sort(all(pos), [](const pii a, const pii b) { return a.first == b.first ? a.second > b.second : a.first < b.first; });
	bool okay = 1;
	int ans = 0;

	while (1)
	{
		cppo = pos;
		int th = upper_bound(pos.begin(), pos.end(), pii{cur, -oo}, [](const pii a, const pii b) { return a.first == b.first ? a.second > b.second : a.first < b.first; }) - pos.begin();
		if (th)
		{ //有正数的
			sort(cppo.begin(), cppo.begin() + th, [](const pii a, const pii b) { return a.second > b.second; });
			cur += cppo[0].second;
			pos.erase(find(all(pos), cppo[0]));
			++ans;
		}
		else break;
	}
	vector<vector<int>> dp(neg.size() + 1, vector<int>(cur + 1, 0));
	dp[0][cur] = ans;
	int res = 0;
	_for(i, 0, neg.size())
	{
		_rep(j, 0, cur)
		{
			if (j >= max(neg[i].first, -neg[i].second))
			{
				dp[i + 1][j + neg[i].second] = max(dp[i + 1][j + neg[i].second], dp[i][j] + 1);
			}
			
			dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
			
		}
	}
	_rep(i, 0, cur)
	{
		res = max(res, dp[neg.size()][i]);
	}
	cout << res << endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"><p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p><div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"><video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video></div><table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody></table><p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p><p> </p><p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p></div>
最新发布
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值