ZOJ 3213 Beautiful Meadow 简单路径 插头DP

  简单路径的题目,其实就是在状态后面多记了有多少个独立插头。

  分类讨论独立插头:

  1、只存在上插头或者左插头,可以选择作为独立插头。

  2、都不存在上插头和左插头,选择作为独立插头的同时要标号为新的连通块。

  换行时需特别注意,因为还有独立插头的判断,如果进行了换行操作,就会乱,特别是在不存在上插头和左插头的情况下。

  那要怎么办呢?

  我们会发现,换行后,1~m-1往后移,并把code[0]设为0,但我们在encode的时候,code[0] = 0,其实是可以忽略的操作,那么我们只需要做M-1就可以了。

  这样想来,就可以去掉shift的操作了。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
 10 #define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
 11 #define mset(a, b) memset(a, b, sizeof(a))
 12 const int MAXD = 15, HASH = 30007, STATE = 1000010; 
 13 int n, m, maze[MAXD][MAXD], code[MAXD], ch[MAXD];
 14 int text[MAXD];
 15 
 16 void Ckmax(int &AI, int BI) { if (AI < BI) AI = BI; }
 17 
 18 struct HASHMAP
 19 {
 20     int head[HASH], nxt[STATE], state[STATE], f[STATE], siz;
 21     void clear() { siz = 0, mset(head, -1); }
 22     void push(int x, int add)
 23     {
 24         int pos = x%HASH, i = head[pos];
 25         for (; i != -1; i = nxt[i])
 26             if (state[i] == x) { Ckmax(f[i], add); return ; }
 27         state[siz] = x, f[siz] = add;
 28         nxt[siz] = head[pos], head[pos] = siz++;
 29     }
 30 }hm[2];
 31 
 32 void in()
 33 {
 34     scanf("%d %d", &n, &m), mset(maze, 0);
 35     REP(i, 1, n)
 36         REP(j, 1, m) scanf("%d", &maze[i][j]);
 37 }
 38 
 39 void decode(int x)
 40 {
 41     DWN(i, m+1, 0) code[i] = x&7, x >>= 3;
 42 }
 43 
 44 int encode(int j)//WRONG 由于换行不能修改,要这样做 
 45 {
 46     int ret = 0, cnt = 0, lim = (j == m) ? m-1 : m;
 47     mset(ch, -1), ch[0] = 0;
 48     REP(i, 0, lim)
 49     {
 50         if (ch[code[i]] == -1) ch[code[i]] = ++cnt;
 51         ret <<= 3, ret |= ch[code[i]];
 52     }
 53     ret <<= 3, ret |= code[m+1];
 54     return ret;
 55 }
 56 
 57 void dp_blank(int i, int j, int cur)
 58 {
 59     REP(k, 0, hm[cur].siz-1)
 60     {
 61         decode(hm[cur].state[k]);
 62         int lef = code[j-1], up = code[j];
 63         if (lef && up)
 64         {
 65             if (lef == up) continue ;
 66             REP(t, 0, m)
 67                 if (code[t] == up) code[t] = lef;
 68             code[j-1] = code[j] = 0;
 69             hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
 70         }
 71         else
 72         {
 73             if (lef || up)
 74             {
 75                 int t = lef ? lef : up;
 76                 if (maze[i][j+1])
 77                 {
 78                     code[j-1] = 0, code[j] = t;
 79                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
 80                 }
 81                 if (maze[i+1][j])
 82                 {
 83                     code[j-1] = t, code[j] = 0;
 84                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
 85                 }
 86                 if (code[m+1]++ < 2)
 87                 {
 88                     code[j-1] = code[j] = 0;
 89                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
 90                 }
 91             }
 92             else
 93             {
 94                 hm[cur^1].push(encode(j), hm[cur].f[k]);
 95                 if (maze[i][j+1] && maze[i+1][j])//WRONG
 96                 {
 97                     code[j-1] = code[j] = 13;
 98                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
 99                 }
100                 if (code[m+1]++ > 1) continue ;
101                 if (maze[i][j+1])
102                 {
103                     code[j-1] = 0, code[j] = 13;
104                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
105                 }
106                 if (maze[i+1][j])
107                 {
108                     code[j-1] = 13, code[j] = 0;
109                     hm[cur^1].push(encode(j), hm[cur].f[k]+maze[i][j]);
110                 }
111             }
112         }
113     }
114 }
115 
116 void dp_block(int i, int j, int cur)
117 {
118     REP(k, 0, hm[cur].siz-1)
119     {
120         decode(hm[cur].state[k]);
121         code[j-1] = code[j] = 0;
122         hm[cur^1].push(encode(j), hm[cur].f[k]);
123     }
124 }
125 
126 void work()
127 {
128     int cur = 0, ans = 0;
129     hm[0].clear(), hm[1].clear(), hm[0].push(0, 0);
130     REP(i, 1, n)
131         REP(j, 1, m)
132         {
133             if (maze[i][j]) dp_blank(i, j, cur);
134             else dp_block(i, j, cur);
135             hm[cur].clear(), cur ^= 1;
136             Ckmax(ans, maze[i][j]);
137         }
138     REP(i, 0, hm[cur].siz-1) Ckmax(ans, hm[cur].f[i]);
139     printf("%d\n", ans);
140 }
141 
142 int main()
143 {
144     int T;
145     scanf("%d", &T);
146     while (T --) in(), work();
147     return 0;
148 }
View Code

 

转载于:https://www.cnblogs.com/-ZZB-/p/6435705.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作据库,这大大简化了据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 据库引擎和连接池: SQLAlchemy 支持多种据库后端,并且为每种后端提供了对应的据库引擎。 它还提供了连接池管理功能,以优化据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值