题目大意:

从左上角走到右下角,每个点之多经过一次,取到所有路径上经过点的权值,求最大的权值之和,这里走到右下角就算停止了

这里有个思路是转化成熟悉的回路问题

在上方和右方最外围定义一圈权值为0 , 那么我们相当于从定义以后的左上角开始经过所有外围点形成的回路,那么去掉最外围的0,剩下的就是(1,1)-》(n,n)的权值和了

但是这里最外围的点的插头具有特殊性,每次到最外围的点,你左和上有且仅有一个插头,而且出去的方向必然是下一个最外围的点

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5
  6 using namespace std;
  7 #define ll long long
  8 const int HASH = 10007;
  9 const int STATE = 1000010;
 10 const int MAXD = 15;
 11 int  n , m;
 12 int code[MAXD] , mp[MAXD][MAXD];
 13 bool flag[MAXD][MAXD];//标记位,标记当前点能否作为最终点
 14 ll ans = 0;
 15 int w[MAXD][MAXD];
 16 struct HASHMAP{
 17     int head[HASH] , next[STATE] , state[STATE] , size;
 18     ll f[STATE];
 19
 20     void init(){
 21         size = 0;
 22         memset(head , -1 , sizeof(head));
 23     }
 24
 25     void push_in(int st , ll sum){
 26         int h = st%HASH;
 27         for(int i = head[h] ; ~i ; i=next[i]){
 28             if(st == state[i]){
 29                 f[i]=max(f[i] , sum); //这题目为求最大值
 30                 return ;
 31             }
 32         }
 33         f[size]=sum;
 34         state[size] = st;
 35         next[size] = head[h];
 36         head[h] = size++;
 37     }
 38 }hashmap[2];
 39
 40 int num = 0;//记录共有的插头数量
 41 void decode(int *code , int m , int st)
 42 {
 43     num = 0;
 44     for(int i=m ; i>=0 ; i--){
 45         code[i] = st&3;
 46         st>>=2;
 47         if(code[i]) num++;
 48     }
 49 }
 50
 51 int encode(int *code , int m)
 52 {
 53     int st=0;
 54     for(int i=0 ; i<=m ; i++){
 55         st<<=2;
 56         st |= code[i];
 57     }
 58     return st;
 59 }
 60
 61 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
 62 {
 63     for(int i=m ; i>=0 ; i--) code[i] = code[i-1];
 64     code[0] = 0;
 65 }
 66
 67 void dpblank(int i , int j , int cur)
 68 {
 69     int k , left , up;
 70     for(k=0 ; k<hashmap[cur].size ; k++){
 71         decode(code , m , hashmap[cur].state[k]);
 72         left = code[j-1];
 73         up = code[j];
 74         if(!left && !up){
 75             if(mp[i][j]==2) continue;
 76             if(mp[i][j]==1){
 77                 if(j == m) shift(code , m);
 78                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 79             }
 80             if(mp[i][j+1] && mp[i+1][j]){
 81                 code[j-1] = 1 , code[j] = 2;
 82                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
 83             }
 84         }
 85         else if(!left && up){
 86             if(mp[i][j]==2 && (up!=2)) continue;
 87             else if(mp[i][j]==2){
 88                 if(mp[i][j+1]==2) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
 89                 else{
 90                     code[j-1] = up , code[j] = 0;
 91                     if(j == m) shift(code , m);
 92                     hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
 93                 }
 94                 continue;
 95             }
 96             if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
 97             if(mp[i+1][j]){
 98                 code[j-1] = up , code[j] = 0;
 99                 if(j == m) shift(code , m);
100                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
101             }
102         }
103         else if(left && !up){
104             if(mp[i][j]==2 && (left!=2)) continue;
105             else if(mp[i][j]==2){
106                 if(mp[i][j+1]==2){
107                     code[j-1] = 0 , code[j] = left;
108                     hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
109                 }else{
110                     if(j == m)  shift(code , m);
111                     hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
112                 }
113                 continue;
114             }
115             if(mp[i+1][j]){
116                 if(j == m)  shift(code , m);
117                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
118             }
119             if(mp[i][j+1]){
120                 code[j-1] = 0 , code[j] = left;
121                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
122             }
123         }
124         else if(mp[i][j]==2) continue;
125         else if(left==1 && up == 1){
126             int cnt = 1;
127             for(int v=j+1 ; v<=m ; v++){
128                 if(code[v]==1)cnt++;
129                 if(code[v]==2)cnt--;
130                 if(!cnt){
131                     code[v]=1;
132                     break;
133                 }
134             }
135             code[j-1] = code[j] = 0;
136             if(j == m) shift(code , m);
137             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
138         }
139         else if(left == 2 && up == 2){
140             int cnt=1;
141             for(int v=j-2 ; v>=1 ; v--){
142                 if(code[v]==2)cnt++;
143                 if(code[v]==1)cnt--;
144                 if(!cnt){
145                     code[v]=2;
146                     break;
147                 }
148             }
149             code[j-1] = code[j] = 0;
150             if(j == m) shift(code , m);
151             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
152         }
153         else if(left==1 && up==2){
154             if(i==n && j==m) ans=max(ans,hashmap[cur].f[k]+w[i][j]);
155         }
156         else{
157             code[j-1]=code[j]=0;
158             if(j == m) shift(code , m);
159             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]);
160         }
161     }
162 }
163
164 void init()
165 {
166     for(int i=1 ; i<=m+1 ; i++) mp[1][i]=2 , w[1][i] = 0;
167     for(int i=2 ; i<=n+1 ; i++){
168         for(int j=1 ; j<=m ; j++)
169             scanf("%d" , &w[i][j]) , mp[i][j]=1;
170         w[i][m+1] = 0 , mp[i][m+1] = 2;
171         mp[i][m+2] = mp[n+2][i]=0;
172     }
173
174     n++ , m++;
175     mp[1][1] = mp[n][m] = 1;
176     /*for(int i=1 ; i<=n ; i++){
177         for(int j=1 ;j <=m ; j++){
178             cout<<mp[i][j]<<" ";
179         }
180         cout<<endl;
181     }*/
182 }
183
184 ll solve()
185 {
186     ans = -1e9;
187     int cur = 0;
188     hashmap[cur].init();
189     hashmap[cur].push_in(0 , 0);
190     for(int i=1 ; i<=n ; i++){
191         for(int j=1 ; j<=m ; j++){
192             hashmap[cur^1].init();
193             dpblank(i , j , cur);
194             cur ^= 1;
195           /* cout<<"test: "<<i<<" "<<j<<endl;
196                 for(int k=0 ; k<hashmap[cur].size ; k++)
197                 cout<<hashmap[cur].f[k]<<endl;*/
198
199         }
200     }
201    // for(int i=0 ; i<hashmap[cur].size ; i++)
202     return ans;
203 }
204
205 int main()
206 {
207   //  freopen("in.txt" , "r" , stdin);
208     int cas = 0;
209     while(~scanf("%d%d" , &n , &m))
210     {
211         init();
212         printf("Case %d: ",++cas);
213         if(n==1 && m==1){
214             printf("%d\n" , w[1][1]);
215             continue;
216         }
217         printf("%I64d\n" , solve());
218     }
219     return 0;
220 }

转载于:https://www.cnblogs.com/CSU3901130321/p/4730904.html

HDU 3377 插头dp相关推荐

  1. HDU1693 Eat The Trees(插头dp)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1693 Eat the Trees Time Limit: 4000/2000 MS (Java/Othe ...

  2. 插头DP题目泛做(为了对应WYD的课件)

    题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. 1 #i ...

  3. 轮廓线DP(插头DP 裸 经典骨牌)

    引言:所谓轮廓线,不是某一行,或者某一列,而是指某一个特定轮廓的状态. 放置骨牌的约定:(保证放置有最优子结构) 假设我们正在放置第i行的骨牌,那么会有下面3种方式: 灰色表示已经有的骨牌,绿色表示新 ...

  4. 好学易懂 从零开始的插头DP(三)

    好学易懂 从零开始的插头DP(三) 写在前面 这篇文章主要是介绍一些括号表示法和简单回路的基本变化,下一篇会是一些非回路(最小表示),毒瘤状态(正wa着所以咕着),结合矩阵乘法加速等一些复杂应用.下下 ...

  5. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 924  Solved: 351 [Submit][S ...

  6. [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识--这真的是一种很锻炼人的题型-- 每一道题的状态都不一样 ...

  7. HDU4084 插头dp

    题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法 思路:插头DP或轮廓线,多加一维DP讨论就可以 注意插头DP状 ...

  8. POJ3133(插头dp)

    传送门:http://poj.org/problem?id=3133 Manhattan Wiring Time Limit: 5000MS   Memory Limit: 65536K       ...

  9. P3272 [SCOI2011]地板(插头DP)

    [题面链接] https://www.luogu.org/problemnew/show/P3272 [题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数 [题解] ( ...

最新文章

  1. windows Azure
  2. 使用游戏测试干式EEG传感器的有效性
  3. 无效字符 java_Java知识查漏补缺
  4. GEMM算法及优化流程详解
  5. React之回调函数形式的ref
  6. 没有bug队——加贝——Python 练习实例 7,8
  7. 自己封装的Windows7 64位旗舰版,微软官网上下载的Windows7原版镜像制作,绝对纯净版...
  8. android java.net.ConnectException: Connection 127.0.0.1:8080 refused
  9. 通过自定义类加载器进行动态编译与动态实现接口
  10. ElasticSearch的优点
  11. Vivado:信道编码卷积编码和RS编码IP核
  12. 技术经理应该具备哪些方面的能力
  13. android 手机远程助手,安卓远程桌面软件
  14. 超详细的Python面向对象编程讲解
  15. python .center用法_python之testcenter操作
  16. 怎么看电脑是32位还是64位?超级简单的方法!
  17. Python廖雪峰教程学习笔记:Day4
  18. 七星彩长奖表图_2020海南七星彩奖表图最新
  19. 如何让DEDECMS织梦的TAGS标签静态化
  20. linux性能分析 -- top

热门文章

  1. 带你自学Python系列(四):range、min、max、sum函数
  2. 《Python编程从入门到实践》记录之input()函数
  3. 算法训练和模型部署如何避免多次重写数据预处理代码
  4. 弄潮儿数据_SINX 信息数据的“弄潮儿”
  5. 用python写helloworld_Python基于Tkinter的HelloWorld入门实例
  6. Docker 容器遇到的乱码问题
  7. 基于Web的浮动图片墙
  8. cisco 通过tftp备份/恢复配置和3560交换机IOS升级
  9. fast-planner 安装
  10. jQuery 中$('.classname').on('click',function(){});与$(document).on('click','.classname',function(){});