我们今天来学习插头DP???

BZOJ 2595:[Wc2008]游览计划

Input

第一行有两个整数,N和 M,描述方块的数目。

接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;

否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,

行首行末也可能有多余的空格。

Output

由 N + 1行组成。第一行为一个整数,表示你所给出的方案

中安排的志愿者总数目。

接下来 N行,每行M 个字符,描述方案中相应方块的情况:

z ‘_’(下划线)表示该方块没有安排志愿者;

z ‘o’(小写英文字母o)表示该方块安排了志愿者;

z ‘x’(小写英文字母x)表示该方块是一个景点;

注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不

一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。

Sample Input

4 4

0 1 1 0

2 5 5 1

1 5 5 1

0 1 1 0

Sample Output

6

xoox

___o

___o

xoox

题解

我们可以不考虑括号表示法(像什么独立插头什么的),这道题我们考虑一下最小表示法

我们对于每个联通块标一个号,最后要求所有联通块在一起并且要求某些格子必须选,选格子有一定的价值,求最小价值

我们对于一个格子先判断选择和不选

有几种情况必须选

1.这个点是景点

2.这个点的上面有插头而这一个轮廓线上没有别的插头连通性和上面这个插头的连通性相同了

那么不选就直接把这个东西的插头改成0

然后选的话

如果上下都没有插头,新建一个连通块

如果左边有插头而上面没有插头,那么连通性从旁边过继过来

如果左边有插头上面也有插头,把这个轮廓线上所有的和左插头连通性相同的改成上插头的连通性

这个就是最小表示法啦!

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
//#define ivorysi
#define MOD 97171
using namespace std;
typedef long long ll;
struct node {
int next,val,pre,pos,state;
bool choose;
}edge[1000005];
int sumedge;
struct HashType {
int head[MOD + 5],lastsum;
void init() {
memset(head,0,sizeof(head));
lastsum = sumedge + 1;
}
void Insert(const int &S,const int &cost,const int &pos,const int &pre,const bool &flag) {
int x = S % MOD;
for(int i = head[x] ; i ; i = edge[i].next) {
if(edge[i].state == S) {
if(cost < edge[i].val) {
edge[i].val = cost;
edge[i].pre = pre;
edge[i].pos = pos;
edge[i].choose = flag;
}
return ;
}
} edge[++sumedge].val = cost;
edge[sumedge].state = S;
edge[sumedge].pre = pre;
edge[sumedge].pos = pos;
edge[sumedge].choose = flag;
edge[sumedge].state = S;
head[x] = sumedge;
}
}cur,last;
int n,m,mapv[15][15];
int conj[15],mp[10],ans,lastedge;
bool g[15][15];
void decode(int state) {
for(int i = m ; i >= 1 ; --i) {
conj[i] = state & 7;
state >>= 3;
}
}
int encode() {
int x = 0 , tot = 0;
memset(mp,-1,sizeof(mp));
mp[0] = 0;
for(int i = 1 ; i <= m ; ++i) {
if(mp[conj[i]] == -1) mp[conj[i]] = ++tot;
conj[i] = mp[conj[i]];
x = x << 3 | conj[i];
}
return x;
}
void DP(int x,int y,int id) {
decode(edge[id].state);
int west = conj[y - 1];
int north = conj[y];
int nxt;
bool flag;
if(mapv[x][y] == 0) flag = 0;
else if(!north) flag = 1;
else {
flag = 0;
for(int i = 1 ; i <= m && !flag; ++i) {
if(i != y && conj[i] == north) flag = 1;
}
}
if(flag) {
conj[y] = 0;
nxt = encode();
cur.Insert(nxt,edge[id].val,(x - 1) * m + y,id,0);
conj[y] = north;
}
if(!north && !west) conj[y] = 7;
else if(!north && west > 0) conj[y] = west;
else if(west > 0 && north > 0 && west !=north){
for(int i = 1; i <= y ; ++i) {
if(conj[i] == west) conj[i] = north;
}
}
nxt = encode();
cur.Insert(nxt,edge[id].val + mapv[x][y],(x - 1) * m + y ,id,1);
}
void Update(int id) {
decode(edge[id].state);
for(int i = 1 ; i <= m ; ++i) {
if(conj[i] > 1) return;
}
if(edge[id].val < ans) {
ans = edge[id].val;
lastedge = id;
}
}
void getans(int id) {
if(id <= 0) return;
int r = edge[id].pos;
int l = (r - 1) / m + 1;
r = (r - 1) % m + 1;
g[l][r] = edge[id].choose;
getans(edge[id].pre);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
ans = 0x7fffffff;
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
scanf("%d",&mapv[i][j]);
}
}
last.Insert(0,0,101,0,0);
last.lastsum = 1;
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
cur.init();
for(int k = sumedge ; k >= last.lastsum ; --k) {
DP(i,j,k);
}
last = cur;
}
}
for(int k = sumedge ; k >= last.lastsum ; --k) {
Update(k);
}
printf("%d\n",ans);
getans(lastedge);
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
if(mapv[i][j] == 0) putchar('x');
else if(g[i][j]) putchar('o');
else putchar('_');
}
putchar('\n');
}
}

BZOJ 1187: [HNOI2007]神奇游乐园

Time Limit: 10 Sec Memory Limit: 162 MB

Submit: 1280 Solved: 687

[Submit][Status][Discuss]

Description

经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回。在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼。往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计。娱乐场可以看成是一块大小为n×m的区域,且这个n×m的区域被分成n×m个小格子,每个小格子中就有一个娱乐项目。然而,小P并不喜欢其中的所有娱乐项目,于是,他给每个项目一个满意度。满意度为正时表示小P喜欢这个项目,值越大表示越喜欢。为负时表示他不喜欢,这个负数的绝对值越大表示他越不喜欢。为0时表示他对这个项目没有喜恶。小P决定将飞艇停在某个小格中,然后每步他可以移动到相邻的上下左右四个格子的某个格子中。小P希望找一条路径,从飞艇所在格出发,最后又回到这个格子。小P有一个习惯,从不喜欢浪费时间。因此,他希望经过每个格子都是有意义的:他到一个地方后,就一定要感受以下那里的惊险和刺激,不管自己是不是喜欢那里的娱乐项目。而且,除了飞艇所在格,其他的格子他不愿意经过两次。小P希望自己至少要经过四个格子。在满足这些条件的情况下,小P希望自己玩过的娱乐项目的满意度之和最高。你能帮他找到这个最高的满意度之和吗?

Input

输入文件中的第一行为两个正整数n和m,表示游乐场的大小为n×m。因为这个娱乐场很狭窄,所以n和m满足:2<=n<=100,2<=m<=6。接下来的n行,每行有m个整数,第i行第j列表示游乐场的第i行第j列的小格子中的娱乐项目的满意度,这个满意度的范围是[-1000,1000]。同一行的两个整数之间用空格隔开。

Output

输出文件中仅一行为一个整数,表示最高的满意度之和。

Sample Input

4 4

100 300 -400 400

-100 1000 1000 1000

-100 -100 -100 -100

-100 -100 -100 1000

Sample Output

4000

HINT

大家测下这个数据 5 5 1 1 -100 3 3 1 1 -100 3 3 1 1 -100 3 3 1 1 -100 3 3 1 1 -100 3 3 结果是30?

题解

我们来学习括号表示法!

由于一条回路有很多路径拼在一起的,一条路径的左右端点对应一对左右括号

那么一个轮廓线就可以用括号表示

我们分类讨论

我们设上插头为north,左插头为west

设无插头是0,左括号是1,右括号是2

如果north == west == 0

那么我们可以选择跳过这个点

或者新建一个插头,向下延伸的插头是1,向右延伸的插头是2

如果north == west == 1

那么我们连上这个这个格子,然后找到上格子对应的右括号,把它改成左括号

如果north == west == 2

情况和上一个类似

如果north 和 west其中有一个是0,另一个不为0

那么我们可以把有插头的那个格子转移到下边或者右边

如果north == 1 west ==2

我们连上这个地方,然后直接改成无插头,因为这两个路径合并成了一条路径

如果north == 2 west == 1

我们连上,这就构成了一条回路,我们修改成无插头,同时更新答案,这个状态不加入哈希表

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
//#define ivorysi
#define MOD 97171
using namespace std;
typedef long long ll;
struct node {
int next,val,state;
};
struct HashType {
int head[MOD + 5],sumedge;
node edge[1000005];
void Init() {
memset(head,0,sizeof(head));
sumedge = 0;
}
void Insert(const int &S,const int &cost) {
int x = S % MOD;
for(int i = head[x] ; i ; i = edge[i].next) {
if(edge[i].state == S) {
if(cost > edge[i].val) {
edge[i].val = cost;
}
return ;
}
}
edge[++sumedge].val = cost;
edge[sumedge].state = S;
edge[sumedge].next = head[x];
head[x] = sumedge;
}
}*cur,*last;
int conj[10],n,m;
int mapv[105][15],ans;
void decode(int state) {
for(int i = m ; i >= 0 ; --i) {
conj[i] = state & 3;
state >>= 2;
}
}
int encode() {
int x = 0;
for(int i = 0 ; i <= m ; ++i) {
x = x << 2 | conj[i];
}
return x;
}
void DP(int x,int y,int S,int V) {
decode(S);
int north = conj[y];
int west = conj[y - 1];
int nxt;
if(!west && !north) {
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V);
conj[y] = 2;
conj[y - 1] = 1;
nxt = encode();
if(y == m) return;
cur->Insert(nxt,V + mapv[x][y]);
}
if(west == 2 && north == 1) {
conj[y] = conj[y - 1] = 0;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V + mapv[x][y]);
}
if(west == 1 && north == 1) {
conj[y] = conj[y - 1] = 0;
int top = 0;
for(int h = y ;h <= m ; ++h) {
if(conj[h] == 1) --top;
else if(conj[h] == 2) ++top;
if(top == 1) {
conj[h] = 1;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V + mapv[x][y]);
break;
}
}
}
if(west == 2 && north == 2) {
conj[y] = conj[y - 1] = 0;
int top = 0;
for(int h = y ;h >= 1 ; --h) {
if(conj[h] == 1) ++top;
else if(conj[h] == 2) --top;
if(top == 1) {
conj[h] = 2;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V + mapv[x][y]);
break;
}
}
}
if((west == 0 || north == 0) && north + west != 0) {
int w = north + west;
if(y == m) {
conj[m - 1] = w;
conj[m] = 0;
nxt = encode();
nxt >>= 2;
cur->Insert(nxt,V + mapv[x][y]);
return;
}
nxt = encode();
cur->Insert(nxt,V + mapv[x][y]);
swap(conj[y],conj[y - 1]);
nxt = encode();
cur->Insert(nxt,V + mapv[x][y]);
}
if(west == 1 && north == 2) {
conj[y] = conj[y - 1] = 0;
nxt = encode();
if(y == m) nxt >>= 2;
if(nxt == 0) {
ans = max(ans,V + mapv[x][y]);
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
scanf("%d",&mapv[i][j]);
}
}
last = new HashType;
cur = new HashType;
last->Insert(0,0);
ans = -100000000;
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
cur->Init();
for(int k = last->sumedge ; k >= 1 ; --k) {
DP(i,j,last->edge[k].state,last->edge[k].val);
}
swap(last,cur);
}
}
printf("%d\n",ans);
}

Ural 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.

![00e95cac-20da-4b1b-b502-28cb9f561a1d.png][3]

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

input

4 4

**..

....

....

....

output

2

input

4 4

....

....

....

....

output

6

题解

求一个有障碍图的哈密顿回路方案数

和上一道题思路差不多,只不过不能有格不选,有障碍的格子必须上下都是0

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
//#define ivorysi
#define MOD 97171
using namespace std;
typedef long long ll;
struct node {
int next,state;
ll val;
};
struct HashType {
int head[MOD + 5],sumedge;
node edge[2000005];
void Init() {
memset(head,0,sizeof(head));
sumedge = 0;
}
void Insert(const int &S,const ll &cost) {
int x = S % MOD;
for(int i = head[x] ; i ; i = edge[i].next) {
if(edge[i].state == S) {
edge[i].val += cost;
return ;
}
}
edge[++sumedge].state = S;
edge[sumedge].val = cost;
edge[sumedge].next = head[x];
head[x] = sumedge;
}
}*cur,*last;
int conj[15],n,m,ux,uy;
ll ans;
char mapv[15][15];
void decode(int state) {
for(int i = m ; i >= 0 ; --i) {
conj[i] = state & 3;
state >>= 2;
}
}
int encode() {
int x = 0;
for(int i = 0 ; i <= m ; ++i) {
x = x << 2 | conj[i];
}
return x;
}
void DP(int x,int y,int S,ll V) {
decode(S);
int north = conj[y];
int west = conj[y - 1];
int nxt;
if(mapv[x][y] == '*') {
if(!west && !north) {
conj[y] = conj[y - 1] = 0;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V);
}
return ;
}
if(!west && !north) {
conj[y] = 2;
conj[y - 1] = 1;
nxt = encode();
if(y == m) return;
cur->Insert(nxt,V);
}
if(west == 2 && north == 1) {
conj[y] = conj[y - 1] = 0;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V);
}
if(west == 1 && north == 1) {
conj[y] = conj[y - 1] = 0;
int top = 0;
for(int h = y ;h <= m ; ++h) {
if(conj[h] == 1) --top;
else if(conj[h] == 2) ++top;
if(top == 1) {
conj[h] = 1;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V);
break;
}
}
}
if(west == 2 && north == 2) {
conj[y] = conj[y - 1] = 0;
int top = 0;
for(int h = y ;h >= 1 ; --h) {
if(conj[h] == 1) ++top;
else if(conj[h] == 2) --top;
if(top == 1) {
conj[h] = 2;
nxt = encode();
if(y == m) nxt >>= 2;
cur->Insert(nxt,V);
break;
}
}
}
if((west == 0 || north == 0) && north + west != 0) {
int w = north + west;
if(y == m) {
conj[m - 1] = w;
conj[m] = 0;
nxt = encode();
nxt >>= 2;
cur->Insert(nxt,V);
return;
}
nxt = encode();
cur->Insert(nxt,V);
swap(conj[y],conj[y - 1]);
nxt = encode();
cur->Insert(nxt,V);
}
if(west == 1 && north == 2) {
conj[y] = conj[y - 1] = 0;
nxt = encode();
if(nxt == 0 && x == ux && y == uy) ans += V;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= n ; ++i) {
scanf("%s",mapv[i] + 1);
for(int j = 1 ; j <= m ; ++j) {
if(mapv[i][j] != '*') {
ux = i;uy = j;
}
}
}
last = new HashType;
cur = new HashType;
last->Insert(0,1);
for(int i = 1 ; i <= n ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
cur->Init();
for(int k = last->sumedge ; k >= 1 ; --k) {
DP(i,j,last->edge[k].state,last->edge[k].val);
}
swap(last,cur);
}
}
printf("%lld\n",ans);
}

BZOJ 2331: [SCOI2011]地板

Time Limit: 5 Sec Memory Limit: 128 MB

Submit: 1403 Solved: 589

[Submit][Status][Discuss]

Description

lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?

需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

![22.jpg.gif][4]

Input

输入的第一行包含两个整数,R和C,表示客厅的大小。

接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。

Output

输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。

Sample Input

2 2

*_

__

Sample Output

1

HINT

R*C<=100

题解

把R < C打成R > C我是真的瞎……

数组开成10 10的真的是折翼……

好了说说题解吧

这道题的插头和往常的路径题不太一样,我们重新设置一下插头

0 表示没有插头

1 是这个方向上需要延伸一个格子,但是还没有转弯

2 表示这个方向上需要延伸一个格子,但是转过弯了

然后转移,首先我们可以判断,上插头和左插头如果都有数字,且都不为1,那么一定不合法,这个状态就可以跳过

然后如果上插头和左插头为0,这个格子又不是障碍物,那么我们就新建一个

可以把这个格子向下的影响设成1,这就新建了一个_| 或者 L型地板的上半部分

或者向右的影响设成1,那么就新建了一个-|型的上半臂

向下和向右的影响都是2,那么就已经转弯了|-就是这样形状的一个角

如果上插头是1,左插头是0

那么可以上插头继续向下延伸或者转弯

如果上插头是0,左插头是1

和上面的情况类似

如果上插头是2,左插头是0

那么可以继续向下延伸,或者结束这个地板

如果上插头是0,左插头是2

和上面的情况类似

如果上插头是1,左插头是1

注意到_|型地板并不能设置向左的转弯,在这种情况里,我们会合并两个分支的地板,来转移这种形状的地板

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MOD 97171
#define mod 20110520
//#define ivorysi
using namespace std;
typedef long long ll;
int R,C;
char s[105][105],mapv[105][105];
struct node {
int next,state;
ll val;
};
struct HashType {
int head[MOD + 5],sumedge;
node edge[1000005];
void Init() {
memset(head,0,sizeof(head));
sumedge = 0;
}
void Insert(const int &S,const ll &val) {
int x = S % MOD;
for(int i = head[x] ; i ; i = edge[i].next) {
if(edge[i].state == S) {
edge[i].val += val;
edge[i].val %= mod;
return ;
}
}
edge[++sumedge].val = val;
edge[sumedge].state = S;
edge[sumedge].next = head[x];
head[x] = sumedge;
} }*last,*cur;
int conj[15];
ll ans;
void decode(int state) {
for(int i = C ; i >= 0 ; --i) {
conj[i] = state & 3;
state >>= 2;
}
}
int encode() {
int x = 0;
for(int i = 0 ; i <= C ; ++i) {
x = (x << 2) | conj[i];
}
return x;
}
void DP(int x,int y,int S,ll V) {
decode(S);
int north = conj[y];
int west = conj[y - 1];
int nxt;
if(mapv[x][y] == '*') {
if(north == 0 && west == 0) {
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
}
return;
}
if(north == 0 && west == 0) {
conj[y - 1] = 1;
conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
conj[y - 1] = 2;
conj[y] = 2;
if(y != C) nxt = encode() , cur->Insert(nxt,V);
conj[y] = 1;
conj[y - 1] = 0;
if(y != C) nxt = encode() , cur->Insert(nxt,V);
}
if(north == 1 && west == 0) {
conj[y - 1] = 1;conj[y] = 0;
nxt = encode() ;
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
conj[y - 1] = 0;conj[y] = 2;
if(y != C)nxt = encode() , cur->Insert(nxt,V);
}
if(north == 2 && west == 0) {
conj[y - 1] = 2;conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
conj[y - 1] = 0;conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
}
if(north == 0 && west == 1) {
conj[y - 1] = 0;conj[y] = 1;
if(y != C) nxt = encode() , cur->Insert(nxt,V);
conj[y - 1] = 2;conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
}
if(north == 0 && west == 2) {
conj[y - 1] = 0;conj[y] = 2;
if(y != C) nxt = encode() , cur->Insert(nxt,V);
conj[y - 1] = 0;conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
}
if(north == 1 && west == 1){
conj[y - 1] = 0;conj[y] = 0;
nxt = encode();
if(y == C) nxt >>= 2;
cur->Insert(nxt,V);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d%d",&R,&C);
for(int i = 1 ; i <= R ; ++i) {
scanf("%s",s[i] + 1);
}
if(R < C) {
for(int i = 1 ; i <= R ; ++i) {
for(int j = 1 ; j <= C ; ++j) {
mapv[j][i] = s[i][j];
}
}
swap(R,C);
}
else {
for(int i = 1 ; i <= R ; ++i) {
for(int j = 1 ; j <= C ; ++j ){
mapv[i][j] = s[i][j];
}
}
}
last = new HashType;
cur = new HashType;
last->Insert(0,1);
for(int i = 1 ; i <= R ; ++i) {
for(int j = 1 ; j <= C ; ++j) {
cur->Init();
for(int k = last->sumedge ; k >= 1 ; --k) {
DP(i,j,last->edge[k].state,last->edge[k].val);
}
swap(last,cur);
}
}
for(int k = last->sumedge ; k >= 1 ; --k) {
int S = last->edge[k].state;ll V = last->edge[k].val;
if(S == 0) {ans += V;ans %= mod;}
}
printf("%lld\n",ans);
}

插头DP学习笔记——从入门到……????的更多相关文章

  1. 插头DP学习笔记

    插头DP(我也不知道该怎么定义...)是一种类似于洛谷题目([模板]插头DP)的题目 题目特征为: 在棋盘上 某一维的数据范围很小 完全铺满 计数问题 直接看题吧. [模板]插头DP 给出n*m的方格 ...

  2. ural 1519 fomular 1 既插头DP学习笔记

    直接看CDQ在2008年的论文吧. 个人认为她的论文有两个不明确的地方, 这里补充一下: 首先是轮廓的概念. 我们在进行插头DP时, 是从上往下, 从左往右逐个格子进行的, 已经处理的格子与未经处理的 ...

  3. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  4. WebSocket学习笔记——无痛入门

    WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报  分类: 物联网学习笔记(37)  版权声明:本文为博主原 ...

  5. 数位DP学习笔记

    数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...

  6. DP学习笔记

    DP学习笔记 可是记下来有什么用呢?我又不会 笨蛋你以后就会了 完全背包问题 先理解初始的DP方程: void solve() { for(int i=0;i<;i++) for(int j=0 ...

  7. Java学习笔记之---入门

    Java学习笔记之---入门 一. 为什么要在众多的编程语言中选择Java? java是一种纯面向对象的编程语言 java学习起来比较简单,适合初学者使用 java可以跨平台,即在Windows操作系 ...

  8. 插头$DP$学习小结

    插头\(DP\)学习小结 这种辣鸡毒瘤东西也能叫算法... 很优秀的一个算法. 最基本的适用范围主要是数据范围极小的网格图路径计数问题. 如果是像\(Noi2018\)那种的话建议考生在其他两道题难度 ...

  9. DBFlow框架的学习笔记之入门

    什么是DBFlow? dbflow是一款android高性的ORM数据库.可以使用在进行项目中有关数据库的操作.github下载源码 1.环境配置 先导入 apt plugin库到你的classpat ...

随机推荐

  1. Java基础-程序流程控制第二弹(循环结构)

    Java基础-程序流程控制第二弹(循环结构) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 流程控制有三种基本结构:顺序结构,选择结构和循环结构.一个脚本就是顺序结构执行的,选择结 ...

  2. oracle中所有存在不存在的用户都可以使用dba连接到数据库

    oracle中所有存在不存在的用户都可以使用dba连接到数据库及解决方式 以前一直使用conn /as sysdba连接数据库,不明白里面的意思.今天无意中使用其他的用户名密码连接到dba竟然也可以( ...

  3. 科学计算三维可视化---TraitsUI的介绍

    TraitsUI的介绍 Python中存在Tkinter,wxPython,pyQt4等GUI图像界面编写库,这三类库要求程序员掌握众多的GUI API函数 对于科学计算的应用来说,我们希望可以快速的 ...

  4. webapi框架搭建-安全机制(二)-身份验证

    webapi框架搭建系列博客 身份验证(authentication)的责任是识别出http请求者的身份,除此之外尽量不要管其它的事.webapi的authentication我用authentica ...

  5. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  6. SCOI2012喵星球上的点名

    http://codevs.cn/problem/2403/ 2012年省队选拔赛四川  时间限制: 2 s  空间限制: 128000 KB   题目描述 Description a180285幸运 ...

  7. 关于mysql 5.7版本“报[Err] 1093 - You can't specify target table 'XXX' for update in FROM clause”错误的bug

    不同于oracle和sqlserver,mysql并不支持在更新某个表的数据时又查询了它,而查询的数据又做了更新的条件,因此我们需要使用如下的语句绕过: , notice_code ) a) ; 本地 ...

  8. python类和对象-扩展

    1.为类或对象动态创建属性或方法 2.__slots__ = ('name','age'),[实例]只能创建指定的属性属性或方法 ---新式类 3.执行父类的构造函数的不同Father.__init_ ...

  9. Anaconda3+python3环境下如何创建python2环境(win+Linux下适用,同一个anaconda下py2/3共存)

    本人之前已经在anaconda环境下已经安装了python3的环境,现在因为一些需求,要安装python2环境 1.打开anaconda的anaconda prompt查看当前环境: conda in ...

  10. Codeforces 859E Desk Disorder 并查集找环,乘法原理

    题目链接:http://codeforces.com/contest/859/problem/E 题意:有N个人.2N个座位.现在告诉你这N个人它们现在的座位.以及它们想去的座位.每个人可以去它们想去 ...