Magnificent waltz

Title Description

Might think ballroom is a matrix of N rows and M columns, piling up some furniture in certain cells of the matrix, others are open space. Piano can slide on the ground, but can not hit the furniture or out of the ballroom, otherwise it will damage the piano and furniture, the captain drew tough. Each time, the piano will be with a sliding direction of the hull is inclined to the adjacent grid squares, the grid may be adjacent east, west, south or north. And Emily can choose to enchant or no enchant: If you do not do magic, the piano slides; if enchanted, the piano will stay put.

Emily is an angel, she knew inclination of the hull of each period. She wants to make the piano in the ballroom glide away as long as possible, so that 1900 will be very happy, but also conducive to the treatment of Tony's seasick. But Emily is too young, do not count, so I hope you can help her.

Input Format

The first line of the input file contains the 5 number N, M, x, y and K. Size N and M described dance halls, x and y for the initial position of the piano; we inclination of the hull is described by a time interval, and calculates a time from the start, such as "east [1, 3] time tilt, [4, 5] time north tilt ", therefore where K represents the number of sections.

The following N lines of M characters, describing the ballroom furniture. '.' Character i-th row j-th column if it is, it means that the position of the open space; if it is 'X', then furniture.

The following lines K, K time intervals described in order, in the format: si ti di (1 ≤ i ≤ K). Represents the time interval [si, ti] the hull is inclined in the direction di. di is 1, 2, 3, 4 a, respectively for the North, South, West, East (corresponding to the matrix, down, left, right). To ensure that the input section is continuous, i.e.,

s1 = 1 ti = si-1 + 1 (1 <i ≤ K)

tK = T

Output Format

The output file is only one line, contains an integer representing the piano glide longest distance (ie, the number of grid).

Sample input 1

4 5 4 1 3
..xx.
.....
...x.
.....
1 3 4
4 5 1
6 7 3

Sample output

6

Description / Tips

Piano taxi routes:

Angel piano at once magic "×" position, the total length of the slide 6.

【data range】

50% of the data, 1≤N, M≤200, T≤200;

100% of the data, 1≤N, M≤200, K≤200, T≤40000.






首先考虑对于时间t来dp: f[t][i][j]表示在第t时刻在第i行第j列所能获得的最长距离。
转移方程:f[t][i][j]=max(f[t-1][i][j],f[t][i*][j*]+1)(i*,j*为上一个合理的位置)
这样时间复杂度为O(TNM),可以过50%,但对于100%TLE且MLE。 所以必须优化,首先把时间t换成区间k,
令f[k][i][j]表示在第k段滑行区间中在位置i,j所能获得最长距离 注意到在第k段时间内只能向某个方向最多走x步(x为区间长度),
得到转移方程 f[k][i][j]=max(f[k-1][i][j],f[k][i*][j*]+dis(i,j,i*,j*))(i*,j*为上一个合理的位置)
这个做法的时间复杂度是O(kn^3),会超时,需要进一步优化 用单调队列优化掉内层的一个n,就可以做到O(kn^2),
可以AC,本代码中还使用了滚动数组优化 用单调递减队列求最大值时,遇到障碍清空整个队列即可,另外队列比较时需要加上偏移量dis

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

int n, m, sx, sy, K, ans, dp[MAXN][MAXN];
int dx[5]={0, -1, 1, 0, 0}, 
    dy[5]={0, 0, 0, -1, 1}; 
struct node{
    int dp, pos;
}q[MAXN]; //q为单调递减队列,要存位置信息用来计算共走了几步 
char map1[MAXN][MAXN];

void work(int x,int y,int len,int d){ //第k个区间的时长为len,方向为d,起点坐标x,y 
    int head=1,tail=0;
    for(int i=1;x>=1&&x<=n&&y>=1&&y<=m;i++,x+=dx[d],y+=dy[d])
        if(map1[x][y]=='x') 
            head=1,tail=0; //遇到障碍,清空队列 
        else{
            while(head<=tail&&q[tail].dp+i-q[tail].pos<dp[x][y]) 
                tail--;
            q[++tail] = node{dp[x][y], i}; //当前值入队列 
            if(q[tail].pos-q[head].pos>len) 
                head++; //队列长度超过len时队首弹出 
            dp[x][y]=q[head].dp+i-q[head].pos; //最优解是队首元素+移动距离 
            ans = max(ans, dp[x][y]); //记录结果 
        }
}
int main(){
    scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&K);
    for(int i = 1; i <= n; i++) 
        scanf("%s", map1[i] + 1);
    memset(dp, 0xf3, sizeof(dp));
    dp[sx][sy] = 0; //初始化,只有初始位置是0,其他都是负无穷 
    for(int k=1,s,t,d,len;k<=K;k++){
        scanf("%d%d%d",&s,&t,&d);
        len=t-s+1;
        if(d==1) 
            for(int i=1;i<=m;i++) 
                work(n, i, len, d);
        if(d==2) 
            for(int i=1;i<=m;i++) 
                work(1, i, len, d);
        if(d==3) 
            for(int i=1;i<=n;i++) 
                work(i, m, len, d);
        if(d==4) 
            for(int i=1;i<=n;i++) 
                work(i, 1, len, d);
    }
    printf("%d", ans);
}
 

Guess you like

Origin www.cnblogs.com/aprincess/p/11626883.html