URAL1519 Formula 1 —— 插頭DP

題目鏈接:https://vjudge.net/problem/URAL-1519

?

1519. Formula 1

Time limit: 1.0 second
Memory limit: 64 MB

Background

Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it.

Problem

Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said.
It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangle?N*M?cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle's sides, so only right-angled bends may be on the circuit. At the picture below two samples are given for?N?=?M?= 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here.
Problem illustration

Input

The first line contains the integer numbers?N?and?M?(2 ≤?N,?M?≤ 12). Each of the next?N?lines contains?M?characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located. There are at least 4 cells without gopher holes.

Output

You should output the desired number of ways. It is guaranteed, that it does not exceed 263-1.

Samples

inputoutput
4 4
**..
....
....
....
2
4 4
....
....
....
....
6
Problem Author:?Nikita Rybak, Ilya Grebnov, Dmitry Kovalioff
Problem Source:?Timus Top Coders: Third Challenge
Tags:?none ?(hide tags for unsolved problems)

?

?

題意:

用一個回路去走完所有的空格,問有多少種情況?

?

題解:

1.學習插頭DP的必經之路:《基于連通性狀態壓縮的動態規劃問題》

2.HDU1693 Eat the Trees?這題的加強版。

3.相對于HDU1693,由于此題限制了只能用一個回路,所以在處理的時候,需要記錄輪廓線上,每個插頭分別屬于哪個連通分量的,以此避免形成多個回路。

4.由于m<=12,故連通分量最多為12/2 = 6個,再加上沒有插頭的情況,所以輪廓線上每個位置的狀態共有7種,為了加快速度,我們采用8進制對其進行壓縮。

5.對于一條輪廓線,最多有:8^(12+1)種狀態,所以直接用數組進行存儲或者直接枚舉所以狀態是不可行的。但我們知道其中有許多狀態是無效的,所以我們采用哈希表來存在有效狀態,即能解決空間有限的問題,還能減少直接枚舉所需要的時間花費。

?

?

代碼如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF = 2e9;
 15 const LL LNF = 9e18;
 16 const int MOD = 1e9+7;
 17 const int MAXN = 1e5;
 18 const int HASH = 1e4;
 19 
 20 int n, m, last_x, last_y;
 21 bool maze[13][13];
 22 
 23 struct  //注意哈希表的大小
 24 {
 25     int size, head[HASH], next[MAXN];
 26     LL state[MAXN], sum[MAXN];
 27 
 28     void init()
 29     {
 30         size = 0;
 31         memset(head, -1, sizeof(head));
 32     }
 33 
 34     void insert(LL status, LL Sum)
 35     {
 36         int u = status%HASH;
 37         for(int i = head[u]; i!=-1; i = next[i])
 38         {
 39             if(state[i]==status)
 40             {
 41                 sum[i] += Sum;
 42                 return;
 43             }
 44         }
 45         state[size] = status;   //頭插法
 46         sum[size] = Sum;
 47         next[size] = head[u];
 48         head[u] = size++;
 49     }
 50 
 51 }Hash_map[2];
 52 
 53 struct
 54 {
 55     int code[13];   //用于記錄輪廓線上每個位置的插頭狀態
 56     LL encode(int m)    //編碼:把輪廓線上的信息壓縮到一個longlong類型中
 57     {
 58         LL status = 0;
 59         int id[13], cnt = 0;
 60         memset(id, -1, sizeof(id));
 61         id[0] = 0;
 62         for(int i = m; i>=0; i--)   //從高位到低位。為每個連通塊重新編號,采用最小表示法。
 63         {
 64             if(id[code[i]]==-1) id[code[i]] = ++cnt;
 65             code[i] = id[code[i]];
 66             status <<= 3;   //編碼
 67             status += code[i];
 68         }
 69         return status;
 70     }
 71 
 72     void decode(int m, LL status)  //解碼:將longlong類型中輪廓線上的信息解碼到數組中
 73     {
 74         memset(code, 0, sizeof(code));
 75         for(int i = 0; i<=m; i++)   //從低位到高位
 76         {
 77             code[i] = status&7;
 78             status >>= 3;
 79         }
 80     }
 81 
 82     void shift(int m)   //左移:在每次轉行的時候都需要執行。
 83     {
 84         for(int i = m-1; i>=0; i--)
 85             code[i+1] = code[i];
 86         code[0] = 0;
 87     }
 88 
 89 }Line;
 90 
 91 void transfer_blank(int i, int j, int cur)
 92 {
 93     for(int k = 0; k<Hash_map[cur].size; k++)   //枚舉上一個格子所有合法的狀態
 94     {
 95         LL status = Hash_map[cur].state[k]; //得到狀態
 96         LL Sum = Hash_map[cur].sum[k];      //得到數量
 97         Line.decode(m, status);             //對狀態進行解碼
 98         int up = Line.code[j];         //得到上插頭
 99         int left = Line.code[j-1];     //得到下插頭
100 
101         if(!up && !left)        //沒有上、左插頭,新建分量
102         {
103             if(maze[i+1][j] && maze[i][j+1])    //如果新建的兩個插頭所指向的兩個格子可行,新建的分量才合法
104             {
105                 Line.code[j] = Line.code[j-1] = 6;  //為新的分量編號,最大的狀態才為6
106                 Hash_map[cur^1].insert(Line.encode(m), Sum);
107             }
108         }
109         else if( (left&&!up) || (!left&&up) )   //僅有其中一個插頭,延續分量
110         {
111             int line = left?left:up;    //記錄是哪一個插頭
112             if(maze[i][j+1])    //往右延伸
113             {
114                 Line.code[j-1] = 0;
115                 Line.code[j] = line;
116                 Hash_map[cur^1].insert(Line.encode(m), Sum);
117             }
118             if(maze[i+1][j])        //往下延伸
119             {
120                 Line.code[j-1] = line;
121                 Line.code[j] = 0;
122                 if(j==m) Line.shift(m);
123                 Hash_map[cur^1].insert(Line.encode(m), Sum);
124             }
125         }
126         else    //上、左插頭都存在,嘗試合并。
127         {
128             if(up!=left)    //如果兩個插頭屬于兩個聯通分量,那么就合并
129             {
130                 Line.code[j] = Line.code[j-1] = 0;
131                 for(int t = 0; t<=m; t++)   //隨便選一個編號最為他們合并后分量的編號
132                     if(Line.code[t]==up)
133                         Line.code[t] = left;
134                 if(j==m) Line.shift(m);
135                 Hash_map[cur^1].insert(Line.encode(m), Sum);
136             }
137             else if(i==last_x && j==last_y) //若兩插頭同屬一個分量,則只能在最后的可行格中合并,否則會出現多個聯通分量
138             {
139                 Line.code[j] = Line.code[j-1] = 0;
140                 if(j==m) Line.shift(m);
141                 Hash_map[cur^1].insert(Line.encode(m), Sum);
142             }
143         }
144     }
145 }
146 
147 void transfer_block(int i, int j, int cur)
148 {
149     for(int k = 0; k<Hash_map[cur].size; k++)
150     {
151         LL status = Hash_map[cur].state[k]; //得到狀態
152         LL Sum = Hash_map[cur].sum[k];      //得到數量
153         Line.decode(m, status);
154         Line.code[j] = Line.code[j-1] = 0;
155         if(j==m) Line.shift(m);
156         Hash_map[cur^1].insert(Line.encode(m), Sum);
157     }
158 }
159 
160 int main()
161 {
162     char s[15];
163     while(scanf("%d%d", &n, &m)!=EOF)
164     {
165         memset(maze, false, sizeof(maze));
166         for(int i = 1; i<=n; i++)
167         {
168             scanf("%s", s+1);
169             for(int j = 1; j<=m; j++)
170             {
171                 if(s[j]=='.')
172                 {
173                     maze[i][j] = true;
174                     last_x = i;         //記錄最后一個可行格
175                     last_y = j;
176                 }
177             }
178         }
179 
180         int cur = 0;
181         Hash_map[cur].init();   //初始化
182         Hash_map[cur].insert(0, 1); //插入初始狀態
183         for(int i = 1; i<=n; i++)
184         for(int j = 1; j<=m; j++)
185         {
186             Hash_map[cur^1].init();
187             if(maze[i][j])
188                 transfer_blank(i, j, cur);
189             else
190                 transfer_block(i, j ,cur);
191             cur ^= 1;
192         }
193 
194         LL last_status = 0; //最后的輪廓線就是最后一行,且每個位置都沒有插頭
195         LL ans = Hash_map[cur].size?Hash_map[cur].sum[last_status]:0;
196         printf("%I64d\n", ans);
197     }
198 }
View Code

?

轉載于:https://www.cnblogs.com/DOLFAMINGO/p/8004121.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252738.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252738.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252738.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電子透霧與光學透霧監控攝像機區別

當你在瘋狂購物時也目前已知的透霧算法大致可以分為兩大類&#xff1a;一種是非模型的圖像增強方法&#xff0c;通過增強圖像的對比度&#xff0c;滿足主觀視覺的要求來達到清晰化的目的&#xff1b;另一種是基于模型的圖像復原方法&#xff0c;它考查圖像退化的原因&#xff0…

sshfs的掛載與卸載

在CentOS中 sshfs的使用依賴EPEL(只安裝sshfs不會出錯&#xff0c;但是卻無法使用) 掛載 安裝EPEL rpm -i https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 如果這個鏈接失效&#xff0c;可訪問官網http://fedoraproject.org/wiki/EPEL 安裝sshfs…

2018年中國視頻監控行業發展空間巨大 AI技術賦能發展乃是未來必然趨勢

https://bg.qianzhan.com/report/detail/459/190131-c2610ca0.html2019-2024年中國視頻監控設備行業市場需求預測與投資戰略規劃分析報告2019-2024年中國安防行業市場前瞻與投資戰略規劃分析報告2019-2024年中國智能安防行業市場前瞻與投資戰略規劃分析報告2019-2024年中國智能…

FTP下載文件

今天公司有需求&#xff0c;需要從遠程FTP服務器上下載文件到本地代碼。然后看了一下&#xff0c;順便做個記錄 什么是FTP呢&#xff1f; 詳細百度百科 FTP 是File Transfer Protocol&#xff08;文件傳輸協議&#xff09;的英文簡稱&#xff0c;而中文簡稱為“文傳協議”。用…

tomcat啟動報錯The JRE could not be found.Edit the server and change the JRE location

解決&#xff1a; 在Windows->Preferences->Server->Runtime Environments 選擇Tomcat->Edit&#xff0c;在jre中選擇相應的jdk版本&#xff0c;完事。轉載于:https://www.cnblogs.com/Alwaysbecoding/p/10172752.html

tortoisegit推送ssh-key需要輸入用戶信息

修改了測試代碼&#xff0c;卻在提交代碼時候又跳出來請輸入用戶名和密碼, 后來發現&#xff0c;github push有兩種方式&#xff0c;ssh方式和https方式。而https方式是不同的&#xff0c;具體來說&#xff0c;就是url信息的不同&#xff0c;實際的驗證機制也是不同的。當建立了…

2018年中國視頻監控行業現狀及行業發展趨勢分析預測【圖】

一、中國視頻監控行業現狀 中國 2013-2018 年模擬標清視頻監控攝像機和模擬高清視頻監控攝像機的復合增長率分別為-15.2%、 29.6%。 模擬標清視頻監控攝像機需求量不斷下降&#xff0c; 預計 2018 年同比下降 13%&#xff0c; 將下降到 0.38 億臺。 模擬高清視頻監控攝像機需求…

周總結02

周一周二周三周四周五周六 所花時間 &#xff5b;包括上課&#xff5d; 16&#xff1a;50- 17&#xff1a;50 8&#xff1a;00-9&#xff1a;50 15&#xff1a;00-16&#xff1a;00 15&#xff1a;00- 16&#xff1a;30 0 10&#xff1a;10- 12&#xff1a;00 8&#xff…

C#中控制線程池的執行順序

在使用線程池時&#xff0c;當用線程池執行多個任務時&#xff0c;由于執行的任務時間過長&#xff0c;會導制兩個任務互相執行&#xff0c;如果兩個任務具有一定的操作順序&#xff0c;可能會導制不同的操作結果&#xff0c;這時&#xff0c;就要將線程池按順序操作。下面先給…

MySQL觸發器 trigger學習

觸發器&#xff1a;一類特殊的事物。可監視某種數據操作&#xff0c;并觸發相關操作&#xff08;insert/update/delete&#xff09;。表中的某些數據改變&#xff0c;希望同一時候能夠引起其他相關數據改變的需求。 作用&#xff1a;變化自己主動完畢某些語句查詢&#xff0c;加…

如何分析企業未來發展趨勢——以海康威視為例

財務分析主要基于歷史數據&#xff0c;但投資還需要看到企業未來的發展。 在前一篇的財務分析的文章中已經提到過&#xff1a;財務分析只是手段&#xff0c;最終還是要從中發現企業的競爭優勢以及行業的發展趨勢&#xff0c;并以此為基礎&#xff0c;分析企業未來的競爭優勢及…

java與C++的區別

java與C的區別 來源 https://www.cnblogs.com/Allen-rg/p/6692043.html “作為一名C程序員&#xff0c;我們早已掌握了面向對象程序設計的基本概念&#xff0c;而且Java的語法無疑是非常熟悉的。事實上&#xff0c;Java本來就是從C衍生出來的。”  然而&#xff0c;C和Java之…

js調試筆記

js調試方法很多&#xff0c;今天總結一下最實用的的斷點方法: debugger斷點 這個很常見&#xff0c;但許多人不知道其實可以添加條件判斷 if(something){debugger;} source斷點 這個最為常見&#xff0c;不做過多解釋&#xff0c;具體說一下幾個重要圖標: 恢復腳本執行至下一個…

JAVA Spring 事物 ( 已轉賬為例 ) 基于 AOP 注解

<一> 配置為文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:context"http://www.springf…

全球視頻監控設備市場規模分析

權威電子行業研究機構IHS Research發布《中國CCTV與視頻監控設備市場研究報告》顯示&#xff0c;2014年全球視頻監控設備市場143億美元&#xff0c;同比增長14.2%。歐洲、美洲、亞洲都增長低于預期;中國增長高于預期&#xff0c;市場總量達57.1億美元;美國市場雖然出貨量在增加…

vue 新窗口打開外鏈接

背景&#xff1a;vue-router 打開外鏈接 如果使用 a 標簽&#xff0c;會默認加上根路由&#xff0c;導致跳轉失效。那么如何讓 a 標簽點擊跳轉到新窗口&#xff1f;解決方法&#xff1a;html 代碼<a class"a-style" click"linkDownload(https://www.baidu.co…

EasyWeChat微信開放平臺第三方平臺接入

目錄實例化微信服務器推送事件預授權獲取預授權 Code獲取預授權 URLAPI 列表使用授權碼換取公眾號的接口調用憑據和授權信息獲取授權方的公眾號帳號基本信息獲取授權方的選項設置信息設置授權方的選項信息調用授權方 API實例化<?phpuse EasyWeChat\Foundation\Application;…

201521145048《Java程序設計》第11周學習總結

1. 本周學習總結 1.1 以你喜歡的方式&#xff08;思維導圖或其他&#xff09;歸納總結多線程相關內容。 2. 書面作業 本次PTA作業題集多線程 Q1.互斥訪問與同步訪問 完成題集4-4(互斥訪問)與4-5(同步訪問) 1.1 除了使用synchronized修飾方法實現互斥同步訪問&#xff0c;還有什…

修改chrome記住密碼后自動填充表單的背景

2019獨角獸企業重金招聘Python工程師標準>>> input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill {background-color: rgb(250, 255, 189); /* #FAFFBD; */background-image: none;color: rgb(0, 0, 0); } 轉載于:https://my.oschina.net…

2018年我國視頻監控市場趨勢:智能視頻分析進入規模化

在安防領域中&#xff0c;視頻監控無疑是不可缺少的一環。我國是全球視頻安防行業增速最快的國家之一&#xff0c;近年來我國的視頻監控市場經歷了持續強勁的發展。我國視頻監控市場的高速增長反映了對個人安全及財產保護的擔憂增加。為解決該擔憂&#xff0c;公司及個人機構大…