CodeForces - 1498D Bananas in a Microwave(思维+dp)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1498D Bananas in a Microwave(思维+dp)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出 n n n 次操作,初始时有一个 k = 0 k=0 k=0,每次操作抽象为三个数 t   x   y t\\ x\\ y t x y,其中 x x x 可能为小数,可以选择一个 n u m ∈ [ 0 , y ] num\\in[0,y] num[0,y],使得:

  1. t = 1 t=1 t=1:执行 n u m num num k = ⌈ ( k + x ) ⌉ k=\\lceil (k+x) \\rceil k=(k+x)
  2. t = 2 t=2 t=2:执行 n u m num num k = ⌈ ( k ∗ x ) ⌉ k=\\lceil (k*x) \\rceil k=(kx)

问对于 [ 1 , m ] [1,m] [1,m] 的每个数,最少可以通过多少次操作获得,如果无法获得输出 − 1 -1 1

题目分析:读完题第一反应感觉是 b f s bfs bfs,但时间复杂度是 O ( n ∗ m ∗ m ) O(n*m*m) O(nmm) 级别的,因为一共有 n ∗ m n*m nm 个状态,每个状态又可以扩展出 m m m 次,所以显然是不可行的

看了题解后,发现这个模型也可以视为 01 01 01 背包问题,其中,有 n ∗ m n*m nm 个物品,背包容量是 m m m,如果直接暴力的话复杂度显然也是 O ( n ∗ m ∗ m ) O(n*m*m) O(nmm)

不过对于本题而言,有一个很重要的性质,也就是如果某个容量 u u u 可以扩展到 v v v ,且 v v v 之前已经被更新过的话,那么就可以直接 b r e a k break break 了,分两种情况举例一下就明白了:

  1. 假设 u + t = v u+t=v u+t=v,那么 v + 1 v+1 v+1 状态,可以从 u + t + 1 u+t+1 u+t+1 更新,也可以从 v + 1 v+1 v+1 更新
  2. 假设 u ∗ t = v u*t=v ut=v,那么 v ∗ t v*t vt 状态,可以从 u ∗ t 2 u*t^2 ut2 更新,也可以从 v ∗ t v*t vt 更新

所以综上所述,每个状态至多被更新一次,及时剪枝的话时间复杂度实际上是 O ( n ∗ m ) O(n*m) O(nm)

代码:

// Problem: D. Bananas in a Microwave
// Contest: Codeforces - CodeCraft-21 and Codeforces Round #711 (Div. 2)
// URL: https://codeforces.com/contest/1498/problem/D
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e5+100;
const int base=1e5;
bool dp[210][N];
LL t,x,y;
int ans[N];
void update(LL &cur) {
	if(t==1) {
		cur=cur+(x+base-1)/base;
	} else {
		cur=(cur*x+base-1)/base;
	}
}
int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in.txt","r",stdin);
//	freopen("data.out.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int n,m;
	memset(ans,-1,sizeof(ans));
	read(n),read(m);
	dp[0][0]=true;
	for(int i=1;i<=n;i++) {
		read(t),read(x),read(y);
		for(int j=0;j<=m;j++) {
			dp[i][j]=dp[i-1][j];
		}
		for(int j=0;j<=m;j++) {
			if(!dp[i-1][j]) {
				continue;
			}
			LL pos=j;
			for(int t=1;t<=y;t++) {
				update(pos);
				if(pos>m||dp[i-1][pos]) {
					break;
				}
				dp[i][pos]=true;
				ans[pos]=i;
			}
		}
	}
	for(int i=1;i<=m;i++) {
		printf("%d ",ans[i]);
	}
	return 0;
}

以上是关于CodeForces - 1498D Bananas in a Microwave(思维+dp)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Banana 在 JavaScript 中打印? [复制]

再探banana

[ Perl 6 ] 字符串基础操作

array_fill 填充数组内容

在 Datastax Solr 中创建的 Banana 中加载多个内核

ACM-经典DP之Monkey and Banana——hdu1069