• P2254 [NOI2005] 瑰丽华尔兹


    P2254 [NOI2005] 瑰丽华尔兹

    不妨认为舞厅是一个 (N)(M) 列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地。钢琴可以在空地上滑动,但不能撞上家具或滑出舞厅,否则会损坏钢琴和家具,引来难缠的船长。每个时刻,钢琴都会随着船体倾斜的方向向相邻的方格滑动一格,相邻的方格可以是向东、向西、向南或向北的。而艾米丽可以选择施魔法或不施魔法:如果不施魔法,则钢琴会滑动;如果施魔法,则钢琴会原地不动。

    艾米丽是个天使,她知道每段时间的船体的倾斜情况。她想使钢琴在舞厅里滑行的路程尽量长,这样 1900 会非常高兴,同时也有利于治疗托尼的晕船。但艾米丽还太小,不会算,所以希望你能帮助她。

    Solution

    看范围支持 (O(n^{3}))
    想一种暴力的方法, 用 (dp[x][y]) 维护当前操作后, 位于 ((x,y)) 的最长距离
    不用管他是哪个阶段的, 只要能转移获得最大值, 我就用魔法让他一直停在那就行
    然后我们每次船倾斜时, 枚举每一个点, 更新他的dp值
    显然在船倾斜时, 朝向是统一的, 所以更新的依据一定在前面某个区间内
    拿单调队列把每行/列的维护控制在 (O(n)) 即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    #define REP(i, x, y) for(int i = (x);i <= (y);i++)
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 210, inf = 1e9;
    int lenx, leny;
    int sx, sy;
    int n, ans = -inf;
    char map[maxn][maxn];
    int dp[maxn][maxn];
    void init(){
    	lenx = RD(), leny = RD();
    	sx = RD(), sy = RD();
    	n = RD();
    	REP(i, 1, lenx)REP(j, 1, leny){
    		cin>>map[i][j];
    		dp[i][j] = -inf;
    		}
    	dp[sx][sy] = 0;
    	}
    int mx[5] = {0, -1, 1, 0, 0};
    int my[5] = {0, 0, 0, -1, 1};
    struct Que{int val, Index;}Q[maxn];
    void DP(int x, int y, int len, int d){//把从(x, y)沿着d方向运行len的dp全部滚掉一遍
    	int head = 1, tail = 0;
    	for(int i = 1;x && y && x <= lenx && y <= leny;i++, x += mx[d], y += my[d]){
    		if(map[x][y] == 'x')head = 1, tail = 0;//重置
    		else{
    			while(head <= tail && Q[tail].val + i - Q[tail].Index <= dp[x][y])tail--;
    			//因为被滚掉了所以先入队
    			Q[++tail] = (Que){dp[x][y], i};
    			while(head <= tail && i - Q[head].Index > len)head++;
    			if(head <= tail)dp[x][y] = Q[head].val + i - Q[head].Index;
    			ans = max(ans, dp[x][y]);
    			}
    		}
    	}
    void work(){
    	while(n--){
    		int s = RD(), t = RD(), d = RD();
    		if(d == 1)REP(i, 1, leny)DP(lenx, i, t - s + 1, d);
    		if(d == 2)REP(i, 1, leny)DP(1,    i, t - s + 1, d);
    		if(d == 3)REP(i, 1, lenx)DP(i, leny, t - s + 1, d);
    		if(d == 4)REP(i, 1, lenx)DP(i, 1,    t - s + 1, d);
    		}
    	cout<<ans<<endl;
    	}
    int main(){
    	init();
    	work();
    	return 0;
    	}
    
  • 相关阅读:
    TODO supply a title
    three.js ---- 3d页面开发入门
    ProgressBar.Style ---- Marquee
    C#中的Task.Delay()延迟与异步执行返回结果
    位运算-实现加减乘除
    2020年专项附加扣除信息,个税纳税记录查询
    C#动态执行JS和VBS脚本
    windows下bat批处理实现守护进程(有日志)
    C#创建快捷方式的两种方法
    C#中创建程序的快捷方式
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/14546567.html
Copyright © 2020-2023  润新知