UVA 1444 Knowledge for the masses

https://vjudge.net/problem/UVA-1444

题目

你要去图书馆借书,但是书架挡住了你,你没法到图书管理员那里

所有书架都可以左右滑动,但是只能停稳在整数格的位置,于是你决定开辟一条通道

比如这两种方式,你需要推动3个书架。由于你太懒了,只想推动最少的书架。而且你不想走迷宫,只想开辟出一条直的通道。

第一行输出最少推动的书架数量

第二行按照升序输出在什么位置开辟通道需要推动这么多书架

行数>=1,1<=列数<=10^6,书架数+空位数<=2*10^7

时间限制5s

Sample Input

1
4 10
8 1 2 1 0 1 2 0 1
7 2 2 2 1 0 1 0
6 1 3 2 0 2 1
7 2 1 2 0 2 1 0

Sample Output

3
8 9

题解

比较坑,显然没法把所有格子都保存下来,只能保存一排格子。

依次计算每个位置向左推和向右推需要移动多少书架

用一个数组保存当前位置推到第i个空位需要移动多少书架,为了方便计算推多个空位,保存前缀和

那么问题就很简单了,直接模拟,顺便记忆一下哪些位置不能移动,时间复杂度$O(n^2)$……但是记忆一下就可以过时限

暴力乱写居然都过了

2009年欧洲中部区域赛的题目,输出格式没有说明,如果不加空格还会错

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define REPE(i,a,b) for(int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(int i=(a); i>=(b); i--)
using namespace std;
typedef long long ll;
#define MAXN 1000007
unsigned long long ans[MAXN];
bool no[MAXN];
int a[MAXN], b[MAXN], lft[MAXN];
int r,l;
inline void pro() {
	int n; scanf("%d", &n);
	REP(i,0,n) scanf("%d", &a[i]);
	int nowi=0, pos=0; b[0]=0;
	memset(lft,0x3f,sizeof(int)*l);
	REP(i,0,n) {
		if(a[i]==0) {
			nowi++;
			b[nowi]=b[nowi-1];
			lft[pos]=0;
			pos++;
		} else {
			int opos=pos;
			pos+=a[i];
			b[nowi]++;
			for(int c=pos-1, d=nowi-1; c>=opos && d>=0; c--, d--) {
				lft[c]=b[nowi]-b[d];
			}
		}
	}
	nowi=0, pos=l-1; b[0]=0;
	PERE(i,n-1,0) {
		if(a[i]==0) {
			nowi++;
			b[nowi]=b[nowi-1];
			lft[pos]=0;
			pos--;
		} else {
			int opos=pos;
			pos-=a[i];
			b[nowi]++;
			for(int c=pos+1, d=nowi-1; c<=opos && d>=0; c++, d--) {
				lft[c]=min(lft[c], b[nowi]-b[d]);
			}
		}
	}
	REP(i,0,l) if(!no[i]) {
		ans[i]+=lft[i];
		no[i]=lft[i]>=0x3f3f3f3f;
	}
}
inline void go() {
	scanf("%d%d", &r, &l);
	memset(ans,0,sizeof(unsigned long long)*l);
	memset(no,0,sizeof(bool)*l);
	REP(i,0,r) {
		pro();
	}
	int now=0; unsigned long long nma=0x7fffffffffffffffull;
	REP(i,0,l) if(!no[i]) {
		if(ans[i]<nma) {
			nma=ans[i];
			now=1;
			a[0]=i;
		} else if(ans[i]==nma) {
			a[now++]=i;
		}
	}
	printf("%llu
", nma);
	REP(i,0,now) printf("%d ", a[i]);
	putchar('
');
}
int main() {
	int z; scanf("%d", &z);
	while(0<z--) {
		go();
	}
}
原文地址:https://www.cnblogs.com/sahdsg/p/12716651.html