cdoj 1354 柱爷很忙

题目传送门

柱爷很忙

Time Limit: 1000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

柱爷很忙。

柱爷每天不仅要炒股,还要策划和实施抢银行,同时还要水群、回答IOI小朋友们问题,又或者要练习咸鱼神功。

为了能更快完成这些事,把时间拿来玩BattleBlock Theater,柱爷把要做的 N N件事的类型 ai ai原本做的顺序记录下来,计算最少要花费的时间。

万事冥冥之中俱有关联。假如柱爷做事 i i的前一件事是事 j j,所花费的时间为 (ai|aj)(ai&aj) (ai|aj)−(ai&aj),其中 |& |,&是位运算符。若柱爷做事 i i前没有做事,则柱爷要花费的时间为 ai ai

但事情总有轻重缓急之分,按原本顺序的事 i i最多能推迟到做完任意件紧接着事 i i之后的事 ji<ji+bi j,i<j≤i+bi后做,即原本顺序的事 k,k>i+bi k,k>i+bi不能在事 i i之前完成。

柱爷已经知道自己最少要花多少时间了,请问你知道吗。

Input

第一行一个数 N N,代表柱爷要做 N N件事。 1N1000 1≤N≤1000

之后 N N行,每行两个数 aibi ai,bi,代表事情的类型和重要程度。 1ai10000bi7

Output

输出一行一个数,即柱爷最少要花的时间。


题解

由于b <= 7,我们可以使用使用装压。dp[i][j][k],表示考虑前i件事,状态为j,前一件做的事距i为k。

我们考虑对于第i件事,如果它能拖,进行转移。之后考虑做j中的事情进行转移。

具体不好描述,直接上代码。

#include <bits/stdc++.h>
using namespace std;

const int Maxn = 1010, INF = 0x7f7f7f7f;
int a[Maxn], b[Maxn];
int dp[Maxn][(1 << 8) + 10][22];

void SelfMin(int &a, const int &b) {
	if (b < a) a = b; 
}

int Cal(const int &a, const int &b) {
	return (a | b) - (a & b);
}

int main() {
	int n, all = 1 << 8;
	scanf("%d", &n);
	memset(dp, 0x7f, sizeof dp);
	dp[0][all - 1][19] = 0;
	for (int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
	for (int i = 0; i <= n; ++i) 
	for (int j = 0; j < all; ++j)
	for (int k = 0; k < 20; ++k) 
		if (dp[i][j][k] != INF) {
			int ed = min(8, i), CanOff = INF;
			for (int p = ed - 1; p >= 0; --p) 
				if (((j >> p) & 1) == 0) SelfMin(CanOff, i - p + b[i - p]);
			if ((j >> 7) & 1) SelfMin(dp[i + 1][(j ^ (1 << 7)) << 1][min(k + 1, 19)], dp[i][j][k]);
			for (int p = ed - 1; p >= 0 && i - p <= CanOff; --p)
				if (((j >> p) & 1) == 0)
					SelfMin(dp[i][j | (1 << p)][p], 
					dp[i][j][k] + ((k == 19) ? a[i - p] : Cal(a[i - p], a[i - k])));
		}
	int ans = INF;
	for (int i = 0; i < 20; ++i) SelfMin(ans, dp[n][all - 1][i]);
	cout << ans;
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值