• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
AC_Artist.zig_zag
然而我依然在补题、
博客园    首页    新随笔    联系   管理    订阅  订阅

bzoj1499 [NOI2005]瑰丽华尔兹

很容易想出O(NMT)的算法,枚举时间,然后枚举位置,转移就好了,大概是f[t][i][j]=max(f[t-1][i][j],f[t-1][i-dx[t]][j-dy[t]]+1)  dx,dy表示某时刻的滑行方向。这样显然过不了,但是看到每一时间段滑行的方向是相同的,也就是只会在一条直线上转移,于是可以用单调队列维护这一条线上的最优值。当某位置是障碍的时候,这个点不能转移或者被转移,那么清空队列;当转移长度大于时间段长度的时候,当前值不合法,需要后移队首指针;当不动比队尾还要优的时候,队尾永远不可能成为最优值,那么前移队尾指针。这样枚举时间段,枚举位置就可以了,O(NMK)。

adv1900
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #define maxn 220
 7 #define inf 2147483647
 8 using namespace std;
 9 char map[maxn][maxn];
10 int f[2][maxn][maxn],q[maxn];
11 int n,m,p,sx,sy,st,ed,dir,now,last,ans;
12 
13 int main()
14 {
15     scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&p);
16     for (int i=1;i<=n;i++) scanf("%s",map[i]+1);
17     now=1; last=0;
18     memset(f,200,sizeof(f));
19     if (map[sx][sy]!='x') f[now][sx][sy]=0;
20     for (int k=1;k<=p;k++)
21     {
22         scanf("%d%d%d",&st,&ed,&dir);
23         int len=ed-st+1;
24         now^=1; last^=1;
25         memset(f[now],200,sizeof(f[now]));
26         switch (dir)
27         {
28             case 1:
29                 for (int j=1;j<=m;j++)
30                 {
31                     int head=1,tail=0;
32                     for (int i=n;i>=1;i--)
33                     {
34                         f[now][i][j]=f[last][i][j];
35                         if (map[i][j]=='x') head=1,tail=0;
36                         while (head<=tail&&f[last][i][j]>f[last][q[tail]][j]+q[tail]-i) tail--;
37                         q[++tail]=i;
38                         while (head<=tail&&i+len<q[head]) head++;
39                         if (head<=tail) f[now][i][j]=max(f[now][i][j],f[last][q[head]][j]+q[head]-i);
40                     }
41                 }                        
42                 break;
43             case 2:
44                 for (int j=1;j<=m;j++)
45                 {
46                     int head=1,tail=0;
47                     for (int i=1;i<=n;i++)
48                     {
49                         f[now][i][j]=f[last][i][j];
50                         if (map[i][j]=='x') head=1,tail=0;
51                         while (head<=tail&&f[last][i][j]>f[last][q[tail]][j]+i-q[tail]) tail--;
52                         q[++tail]=i;
53                         while (head<=tail&&i-len>q[head]) head++;
54                         if (head<=tail) f[now][i][j]=max(f[now][i][j],f[last][q[head]][j]+i-q[head]);
55                     }
56                 }
57                 break;
58             case 3:
59                 for (int i=1;i<=n;i++)
60                 {
61                     int head=1,tail=0;
62                     for (int j=m;j>=1;j--)
63                     {
64                         f[now][i][j]=f[last][i][j];
65                         if (map[i][j]=='x') head=1,tail=0;
66                         while (head<=tail&&f[last][i][j]>f[last][i][q[tail]]+q[tail]-j) tail--;
67                         q[++tail]=j;
68                         while (head<=tail&&j+len<q[head]) head++;
69                         if (head<=tail) f[now][i][j]=max(f[now][i][j],f[last][i][q[head]]+q[head]-j);
70                     }
71                 }
72                 break;
73             case 4:
74                 for (int i=1;i<=n;i++)
75                 {
76                     int head=1,tail=0;
77                     for (int j=1;j<=m;j++)
78                     {
79                         f[now][i][j]=f[last][i][j];
80                         if (map[i][j]=='x') head=1,tail=0;
81                         while (head<=tail&&f[last][i][j]>f[last][i][q[tail]]+j-q[tail]) tail--;
82                         q[++tail]=j;
83                         while (head<=tail&&j-len>q[head]) head++;
84                         if (head<=tail) f[now][i][j]=max(f[now][i][j],f[last][i][q[head]]+j-q[head]);
85                     }
86                 }
87             break;
88         }
89     }
90     ans=0;
91     for (int i=1;i<=n;i++)
92         for (int j=1;j<=m;j++)
93             if (f[now][i][j]>ans) ans=f[now][i][j];
94     printf("%d\n",ans);
95     return 0;
96 }
97         

 

AC without art, no better than WA !
posted @ 2013-04-23 07:50  Zig_zag  阅读(427)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3