隐藏
「bzoj2310」ParkII - 插头DP | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bzoj2310」ParkII - 插头DP

题目大意

    给一个$n*m$的方格图,要求找一条路径,使得每个点最多经过一次,并且点权值之和最大。


题目分析

上题的区别在于不要求回路,故使用独立插头

同样的无视方格和统计答案的方法做就可以了。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

typedef long long LL;

inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

const int mod=23333;

int n,m,now,Hash[mod],a[105][15],cnt[2],status[2][10005];
LL ans=-1e18,f[2][10005];

#define bit(x) ((x)<<1)

void trans(int s,LL sum) {
int pos=s%mod;
while(Hash[pos]) { //找空位
if(status[now][Hash[pos]]==s) {
f[now][Hash[pos]]=max(f[now][Hash[pos]],sum);
return;
}
pos=(pos+1)%mod;
}
Hash[pos]=++cnt[now];
status[now][Hash[pos]]=s;
f[now][Hash[pos]]=sum;
}

int Find_After(int s,int x) {
int delta=1;
for(int i=x+1; i<=m; i++) {
int val=(s>>bit(i))&3;
if(val==1)delta++;
if(val==2)delta--;
if(!delta)return i;
}
}

int Find_Pre(int s,int x) {
int delta=1;
for(int i=x-1; i>=0; i--) {
int val=(s>>bit(i))&3;
if(val==2)delta++;
if(val==1)delta--;
if(!delta)return i;
}
}

int main() {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++) {
a[i][j]=Get_Int();
ans=max(ans,(LL)a[i][j]);
}
f[0][1]=0;
cnt[0]=1;
status[0][1]=0;
now=0;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
now^=1;
cnt[now]=0;
memset(Hash,0,sizeof(Hash));
for(int k=1; k<=cnt[now^1]; k++) {
int s=status[now^1][k],l=(s>>bit(j-1))&3,r=(s>>bit(j))&3,indep=0;
LL last=f[now^1][k],New=last+a[i][j];
for(int x=0; x<=m; x++)
if(((s>>bit(x))&3)==3)indep++;
if(l==0&&r==0) {
if(i<n&&j<m)trans(s^(1<<bit(j-1))^(2<<bit(j)),New);
if(i<n&&indep<2)trans(s^(3<<bit(j-1)),New);
if(j<m&&indep<2)trans(s^(3<<bit(j)),New);
trans(s,last);
} else if(l==1&&r==0) {
if(j<m)trans(s^(1<<bit(j-1))^(1<<bit(j)),New);
if(i<n)trans(s,New);
int pos=Find_After(s,j-1);
if(indep<2)trans(s^(2<<bit(pos))^(3<<bit(pos))^(1<<bit(j-1)),New);
} else if(l==2&&r==0) {
if(j<m)trans(s^(2<<bit(j-1))^(2<<bit(j)),New);
if(i<n)trans(s,New);
int pos=Find_Pre(s,j-1);
if(indep<2)trans(s^(1<<bit(pos))^(3<<bit(pos))^(2<<bit(j-1)),New);
} else if(l==0&&r==1) {
if(i<n)trans(s^(1<<bit(j))^(1<<bit(j-1)),New);
if(j<m)trans(s,New);
int pos=Find_After(s,j);
if(indep<2)trans(s^(2<<bit(pos))^(3<<bit(pos))^(1<<bit(j)),New);
} else if(l==0&&r==2) {
if(i<n)trans(s^(2<<bit(j))^(2<<bit(j-1)),New);
if(j<m)trans(s,New);
int pos=Find_Pre(s,j);
if(indep<2)trans(s^(1<<bit(pos))^(3<<bit(pos))^(2<<bit(j)),New);
} else if(l==3&&r==0) {
if(j<m)trans(s^(3<<bit(j-1))^(3<<bit(j)),New);
if(i<n)trans(s,New);
if((s^(l<<bit(j-1)))==0)ans=max(ans,New);
} else if(l==0&&r==3) {
if(i<n)trans(s^(3<<bit(j))^(3<<bit(j-1)),New);
if(j<m)trans(s,New);
if((s^(r<<bit(j)))==0)ans=max(ans,New);
} else if(l==1&&r==1) {
int pos=Find_After(s,j);
trans(s^(2<<bit(pos))^(1<<bit(pos))^(1<<bit(j-1))^(1<<bit(j)),New);
} else if(l==2&&r==2) {
int pos=Find_Pre(s,j-1);
trans(s^(1<<bit(pos))^(2<<bit(pos))^(2<<bit(j-1))^(2<<bit(j)),New);
} else if(l==3&&r==1) {
int pos=Find_After(s,j);
trans(s^(2<<bit(pos))^(3<<bit(pos))^(3<<bit(j-1))^(1<<bit(j)),New);
} else if(l==3&&r==2) {
int pos=Find_Pre(s,j);
trans(s^(1<<bit(pos))^(3<<bit(pos))^(3<<bit(j-1))^(2<<bit(j)),New);
} else if(l==1&&r==3) {
int pos=Find_After(s,j-1);
trans(s^(2<<bit(pos))^(3<<bit(pos))^(1<<bit(j-1))^(3<<bit(j)),New);
} else if(l==2&&r==3) {
int pos=Find_Pre(s,j-1);
trans(s^(1<<bit(pos))^(3<<bit(pos))^(2<<bit(j-1))^(3<<bit(j)),New);
} else if(l==2&&r==1)trans(s^(2<<bit(j-1))^(1<<bit(j)),New);
else if(l==3&&r==3&&(s^(l<<bit(j-1))^(r<<bit(j)))==0)ans=max(ans,New);
}
}
for(int j=1; j<=cnt[now]; j++)status[now][j]<<=2;
}
printf("%lld\n",ans);
return 0;
}
姥爷们赏瓶冰阔落吧~