彻彻底底写到自闭的一个专题。

就是大型分类讨论,压行+宏定义很有优势。

常用滚动数组+哈希表+位运算。当然还有轮廓线。

Formula 1:

经过所有格子的哈密顿回路数。

每个非障碍点必须有且仅有2个插头(含上下左右)。

若左上都没有,那么新建两个插头1和2。

若左上只有一个插头,那么它就向右下方向之一延伸。

若左上都有,那么不建新插头。

如果是左1上2,那么就是形成了一条回路,当且仅当在全图右下角更新答案。

如果都是1,那么就要把右边的两个2改成一对插头,就是把靠右的一个1插头匹配的2插头改为1。

都是2同理。

如果是左2上1,那么就是链接了两个路径,两个插头抵消。

 #include<cstdio>
#define cri const register int
int bl[][],n,m,now,last=,ln,lm,fn,fm,r[]={,,-};long long ans;
int read(){
register char ch=getchar();
while(ch!='*'&&ch!='.')ch=getchar();
return ch=='*';
}
struct hash{
int fir[],l[],to[],cnt;long long v[];
void clear(){
for(int i=;i<;++i)to[i]=-,fir[i]=v[i]=;cnt=;
}
long long &operator[](cri pos){
int i;
for(i=fir[pos%];i&&to[i]!=pos;i=l[i]);
if(!i)l[++cnt]=fir[pos%],to[cnt]=pos,fir[pos%]=i=cnt;
return v[i];
}
}f[];
inline int find(cri st,cri p){return st>>(p-<<)&;}
inline void set(int &st,cri p,cri k){st&=~(<<(p-<<));st|=k<<(p-<<);}
inline int get(cri st,cri p){
int dirc=(find(st,p)==)?:-;
for(int i=p,pl=find(st,i),cnt=r[pl];i&&i<=m+;pl=find(st,i+=dirc),cnt+=r[pl])
if(cnt==)return i;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)for(int j=;j<=m;++j){
bl[i][j]=read();
if(!bl[i][j])ln=i,lm=j;
if(!fn&&!bl[i][j])fn=i,fm=j;
}f[][]=;
for(int i=;i<=n;++i)bl[i][m+]=;
for(int i=;i<=m;++i)bl[n+][i]=;
for(int i=fn;i<=n;++i){
for(int j=(i==fn)?fm:;j<=m;++j){
last^=;now^=; f[now].clear();
for(int k=;k<=f[last].cnt;++k){
int st=f[last].to[k],p1=find(st,j),p2=find(st,j+);
long long v=f[last].v[k];//printf("%d %d %d %d %d %lld\n",i,j,st,p1,p2,v);
if(bl[i][j]&&(p1||p2))continue;
if(bl[i][j])f[now][st]+=v;
else if(!p1&&!p2){if(!bl[i][j+]&&!bl[i+][j])set(st,j,),set(st,j+,),f[now][st]+=v;}
else if(p1&&!p2){
if(!bl[i+][j])f[now][st]+=v;//,printf("---%d %d %lld %lld\n",i,j,v,f[now][st]);
if(!bl[i][j+])set(st,j+,p1),set(st,j,),f[now][st]+=v;
}
else if(!p1&&p2){
if(!bl[i][j+])f[now][st]+=v;
if(!bl[i+][j])set(st,j,p2),set(st,j+,),f[now][st]+=v;
}
else if(p1==&&p2==){if(i==ln&&j==lm)ans+=v;}
else if(p2==&&p1==)set(st,j,),set(st,j+,),f[now][st]+=v;
else if(p1==&&p2==)set(st,get(st,j+),),set(st,j,),set(st,j+,),f[now][st]+=v;
else if(p1==&&p2==)set(st,get(st,j),),set(st,j,),set(st,j+,),f[now][st]+=v;
}
}
for(int i=;i<=f[now].cnt;++i)f[now].to[i]<<=;
}
printf("%lld\n",ans);
}

当时我还不会压行

CITY

和上面同理,只不过限制了插头方向。

 #include<cstdio>
#define int long long
#define mod 54321
int n,m,bl[][],ref[],fn,fm,ln,lm,last=,now,tf[]={,,-};long long ans;
int read(){
register char ch=getchar();
while(ch!='.'&&ch!='#'&&ch!='-'&&ch!='|')ch=getchar();
return ref[ch];
}
struct hash{
int fir[mod],l[mod],to[mod],cnt;long long v[mod];
void clear(){for(int i=;i<mod;++i)fir[i]=v[i]=,to[i]=-;cnt=;}
long long &operator[](int p){
int i;
for(i=fir[p%mod];i&&to[i]!=p;i=l[i]);
if(!i)l[++cnt]=fir[p%mod],fir[p%mod]=i=cnt,to[cnt]=p;
return v[i];
}
}f[];
int find(int st,int p){return st>>(p-<<)&;}
void set(int &st,int p,int k){st&=~(<<(p-<<));st|=k<<(p-<<);}
void reset(int &st,int p){
for(int i=p,pl=find(st,i),di=tf[find(st,p)],cnt=di;i&&i<=m+;i+=di,pl=find(st,i),cnt+=tf[pl])
if(!cnt){set(st,i,pl==?:);return;}
}
main(){
scanf("%lld%lld",&n,&m);ref['#']=;ref['-']=;ref['|']=;
for(int i=;i<=n;++i)for(int j=;j<=m;++j){
bl[i][j]=read();
if(!bl[i][j])ln=i,lm=j;
if(!bl[i][j]&&!fn)fn=i,fm=j;
}
f[][]=;
for(int i=;i<=n;++i)bl[i][m+]=;
for(int i=;i<=m;++i)bl[n+][i]=;
for(int i=fn;i<=n;++i){
for(int j=(i==fn?fm:);j<=m;++j){
last^=;now^=;f[now].clear();
for(int k=;k<=f[last].cnt;++k){
int st=f[last].to[k],p1=find(st,j),p2=find(st,j+);long long v=f[last].v[k];//printf("%d %d %d %d %d %lld\n",i,j,st,p1,p2,v);
if(((bl[i][j]&)&&p2)||((bl[i][j]&)&&p1))continue;
if(bl[i][j]==){if(!p1&&!p2)f[now][st]+=v;continue;}
if(bl[i][j]==){if((!(bl[i+][j]&))&&p2&&!p1)set(st,j+,),set(st,j,p2),f[now][st]+=v;continue;}
if(bl[i][j]==){if((!(bl[i][j+]&))&&p1&&!p2)set(st,j,),set(st,j+,p1),f[now][st]+=v;continue;}
if(!p1&&!p2){if(!(bl[i][j+]&)&&!(bl[i+][j]&))set(st,j,),set(st,j+,),f[now][st]+=v;}
else if(p1&&!p2){
if(!(bl[i+][j]&))f[now][st]+=v;
if(!(bl[i][j+]&))set(st,j,),set(st,j+,p1),f[now][st]+=v;
}
else if(p2&&!p1){
if(!(bl[i][j+]&))f[now][st]+=v;
if(!(bl[i+][j]&))set(st,j+,),set(st,j,p2),f[now][st]+=v;
}
else if(p1==&&p2==){if(i==ln&&j==lm)ans+=v;}
else if(p2==&&p1==)set(st,j,),set(st,j+,),f[now][st]+=v;
else if(p1==&&p2==)reset(st,j+),set(st,j,),set(st,j+,),f[now][st]+=v;
else if(p1==&&p2==)reset(st,j),set(st,j,),set(st,j+,),f[now][st]+=v;
}
}
for(int j=;j<=f[now].cnt;++j)f[now].to[j]<<=;
}
printf("%lld\n",ans);
}

我依旧不会压行

邮递员

依旧同理。注意n或m=1。

 #include<cstdio>
#define hash_mod 54321
#define int_mod 100000000000000ll
#define cri const register int
int n,m;
struct gj{
long long x[];
inline void clear(){x[]=x[]=x[]=x[]=x[]=;}
inline void print(){
int i;
for(i=;i>=;--i)if(x[i]){printf("%lld",x[i]);break;}
for(i--;i>=;--i)printf("%014lld",x[i]);puts("");
}
inline void operator+=(const gj &b){
for(int i=;i>=;--i)x[i]+=b.x[i];
for(int i=;i<=;++i)x[i+]+=x[i]/int_mod,x[i]%=int_mod;
}
}ans;
struct hash_map{
int fir[],l[],to[],cnt;gj v[];
void clear(){
for(int i=;i<;++i)fir[i]=,v[i].clear(),to[i]=-;
cnt=;
}
gj &operator[](const int key){
int pos=key%hash_mod,i;
for(i=fir[pos];to[i]!=key&&i;i=l[i]);
if(!i)to[++cnt]=key,l[cnt]=fir[pos],i=fir[pos]=cnt,v[cnt].clear();
return v[i];
}
}hash[];
inline int find(cri st,cri pos){return st>>(pos-<<)&;}
inline int get(cri st,cri pos){
int cnt=,dirc=(find(st,pos)==)?:-;
for(int i=pos,plug=find(st,pos);i&&i<=m+;plug=find(st,i+=dirc)){
if(plug==)cnt++;else if(plug==)cnt--;
if(cnt==)return i;
}
return -;
}
inline void set(int &st,cri pos,cri kind){
st|=<<(pos-<<);st^=<<(pos-<<);
st|=kind<<(pos-<<);
}
void DP(cri x,cri y){
int now=(x-)*m+y&,last=now^,tot=hash[last].cnt;
hash[now].clear();
for(int i=;i<=tot;++i){
int st=hash[last].to[i],plug1=find(st,y),plug2=find(st,y+);
gj v=hash[last].v[i];//printf("%d %d %d %d %d ",x,y,st,plug1,plug2);v.print();
if(get(st,y)==-||get(st,y+)==-)continue;
if(!plug1&&!plug2){if(y!=m&&x!=n)set(st,y,),set(st,y+,),hash[now][st]+=v;}
else if(plug1&&!plug2){
if(x!=n)hash[now][st]+=v;
if(y!=m)set(st,y,),set(st,y+,plug1),hash[now][st]+=v;
}
else if(!plug1&&plug2){
if(y!=m)hash[now][st]+=v;
if(x!=n)set(st,y,plug2),set(st,y+,),hash[now][st]+=v;
}
else if(plug1==&&plug2==){if(x==n&&y==m)ans+=v;}
else if(plug1==&&plug2==)set(st,y,),set(st,y+,),hash[now][st]+=v;
else if(plug1==&&plug2==)
set(st,get(st,y+),),set(st,y,),set(st,y+,),hash[now][st]+=v;
else if(plug1==&&plug2==)
set(st,get(st,y),),set(st,y,),set(st,y+,),hash[now][st]+=v;
}//printf("%d--%d--%d\n",x,y,hash[now].cnt);
}
int main(){
scanf("%d%d",&n,&m);
hash[].clear();hash[][].x[]=;
if(n==||m==){printf("");return ;}
if(n<m)n^=m,m^=n,n^=m;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j)DP(i,j);
if(i!=n){
int now=(i*m)&,tot=hash[now].cnt;
for(int i=;i<=tot;++i)hash[now].to[i]<<=;
}
}
if(ans.x[]==){puts("");return ;}
ans+=ans;ans.print();
}

我还是不会压行

地板

这个插头不太一样。

对于一个L型,其实只有转弯前和转弯后两种状态。分别做1,2。

空格的话,可以把这个点作为拐角,往右下两个方向延伸出两个已经拐弯的插头。

如果只有一个1插头,那么可以选择转弯与否。

如果两个1插头碰在一起,那么它们就在这里转弯,互相抵消。

如果只有一个2插头,那么就延伸就好了。

 #include<cstdio>
#include<cstring>
using namespace std;
#define mod 20110520
#define ad(a,b) add(dp[nx][set(set(st,j,a),j+1,b)],v)
void add(int &a,int b){a+=b;if(a>mod)a-=mod;}
int n,m,dp[][];char s[][];bool a[][];
int find(int st,int num){return st>>num*-&;}
int set(int st,int num,int v){return st^st&<<num*-^v<<num*-;}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)scanf("%s",s[i]+);
if(n<m){
for(int i=;i<=n;++i)for(int j=;j<=m;++j)a[j][i]=s[i][j]=='_';
n^=m^=n^=m;
}else for(int i=;i<=n;++i)for(int j=;j<=m;++j)a[i][j]=s[i][j]=='_';
int nw=,nx=;dp[][]=;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
nw^=;nx^=;
for(int st=;st<<<m*+;++st)if(dp[nw][st]){
int l=find(st,j),u=find(st,j+),v=dp[nw][st];dp[nw][st]=;
if(!a[i][j]){if(l==&&u==)ad(,);continue;}
if(l==&&u==)ad(,),ad(,),ad(,);
else if(l==&&u==)ad(,),ad(,);
else if(l==&&u==)ad(,),ad(,);
else if(l==&&u==)ad(,);
else if(l==&&u==)ad(,),ad(,);
else if(l==&&u==)ad(,),ad(,);
}
}
nw^=;nx^=;
for(int st=;st<<<m*;++st)dp[nx][st<<]=dp[nw][st];
for(int st=;st<<<m*+;++st)dp[nw][st]=;
}printf("%d\n",dp[nx][]);
}

然后我开始压行

标识设计

题意补充:笔画的宽度一定是1,棋盘不用占满,L型不能旋转。

因为不能旋转,所以只有一种插头。

但是不能占满,这个好说,只不过多了一种如果这个格子是空格的话也可以不增加新插头。

然后就退化一下上一题的代码,不过区分一下已经写了几个L就行。

 #include<cstdio>
#include<cstring>
using namespace std;
int dp[][],n,m,w[][],stc,cts[],ans=-,nw,nx=;
int find(int st,int num){return st>>num*&;}
void sch(int al,int st){if(al==m+)cts[++stc]=st;else for(int i=;i<=;++i)sch(al+,st|i<<al*);}
int set(int st,int num,int v){return st^st&<<num*^v<<num*;}
void maxi(int &a,int b){if(a<b)a=b;}
int rmat(int st,int p){for(int i=p+;;++i)if(find(st,i)==)return st-(<<i*);}
int lmat(int st,int p){for(int i=p-;;--i)if(find(st,i)==)return st+(<<i*);}
#define upd(a,b) maxi(dp[nx][set(set(st,j-1,a),j,b)],v)
int main(){
scanf("%d%d",&n,&m);memset(dp,0xa0,sizeof dp);
for(int i=;i<=n;++i)for(int j=;j<=m;++j)scanf("%d",&w[i][j]);
dp[nx][]=;sch(,);
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
nw^=;nx^=;memset(dp[nx],0xa0,sizeof dp[nx]);
for(int p=,st;p<=stc;++p)if(dp[nw][st=cts[p]]>=-){
int p1=find(st,j-),p2=find(st,j),v=dp[nw][st]+w[i][j];
if(p1==&&p2==)upd(,),maxi(dp[nx][st],dp[nw][st]);
if(p1==&&p2==)if(set(set(st,j-,),j,)==)maxi(ans,v);
if(p1==&&p2==)upd(,);
if((p1^p2)==)upd(,),upd(,);
if((p1^p2)==)upd(,),upd(,);
if(p1==&&p2==)maxi(dp[nx][rmat(set(set(st,j-,),j,),j)],v);
if(p1==&&p2==)maxi(dp[nx][lmat(set(set(st,j-,),j,),j)],v);
}
}
nw^=;nx^=;memset(dp[nx],0xa0,sizeof dp[nx]);
for(int p=,st;p<=stc;++p)if(cts[p]<<<m<<m)dp[nx][cts[p]<<]=dp[nw][cts[p]];
}printf("%d\n",ans);
}

压行越发熟练

Park II

毒瘤界的巅峰。

理论上有3个插头,16种情况,但是情况很多重复,所以可以压成9类。

因为这一题是路径而不是回路,而且也不用占满。

为了处理路径的问题,需要引进一种新的插头,就是一端为路径的端点,另一端在轮廓线上的插头,学习LadyLex称之为独立插头3。

所有插头合并情况如下:

1,两个空格:这个格子可以不放,也可以作为拐角放一对12插头,也可以作为路径端点在右下方向之一放一个3插头。

2,两个1/2:与回路的题做法一致。

3,两个3:如果没有其它插头,那么你已经让两个自由端联通了,如果不存在其它插头,那么就可以更新答案。

4,左1上2:在回路题里这样会形成回路,但是路径题不允许回路,所以不做操作。(也就是在代码里不用写出来这种情况)

5,左2上1:与回路的题做法一致。

6,只有一个插头:另一个可以向右下方向之一转弯。

7,只有一个3插头:它可以结束了,作为路径端点,这样的话如果没有其它插头就可以更新答案了。

8,只有一个1/2插头:它可以结束了,作为路径端点,这样的话与1/2配对的2/1插头应该变成孤立的3插头。

9,有一个1/2插头,另一个是3插头:它们匹配了,这样的话与1/2配对的2/1插头应该变成孤立的3插头。
没有其它情况了。

如果宏定义+压行足够优秀,这道题不一定会比前面的题长。

 #include<cstdio>
#include<cstring>
using namespace std;
void maxi(int &a,int b){if(a<b)a=b;}
int set(int st,int p,int v){return st^st&<<p*^v<<p*;}
int get(int st,int p){return st>>p*&;}
int mat(int st,int p,int v,int d,int g,int c=){
for(;;p+=d)if(get(st,p)==g+){c--;if(!c)return st+(v-g-<<p*);}
else if(get(st,p)==(g^)+)c++;
}
int dp[][],w,n,m,nx,nw=,ans,c[],ac[];
#define up(a,b) maxi(dp[nx][set(set(st,j-1,a),j,b)],v)
#define cl set(set(st,j-1,0),j,0)
int main(){
scanf("%d%d",&n,&m);
memset(dp,0xa0,sizeof dp);dp[nx][]=;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
nw^=;nx^=;memset(dp[nx],0xa0,sizeof dp[nx]);scanf("%d",&w);
for(int st=;st<<<m*+;++st)if(dp[nw][st]>-){
int p1=get(st,j-),p2=get(st,j),v=dp[nw][st]+w;
for(int q=;q<;++q)c[q]=;c[p1]++;c[p2]++;
if(c[]==)up(,),up(,),up(,),maxi(dp[nx][st],v-w);
if(c[]==)maxi(dp[nx][mat(cl,j,,,)],v);
if(c[]==)maxi(dp[nx][mat(cl,j,,-,)],v);
if(c[]==)if(!cl)maxi(ans,v);
if(p1==&p2==)up(,);
if(c[]==)up(p1|p2,),up(,p1|p2);
if(c[]&c[])if(!cl)maxi(ans,v);
if(c[]&(c[]|c[]))maxi(dp[nx][mat(cl,j,,,)],v);
if(c[]&(c[]|c[]))maxi(dp[nx][mat(cl,j,,-,)],v);
}
}
nx^=;nw^=;memset(dp[nx],0xa0,sizeof dp[nx]);
for(int st=;st<<<m*;++st)dp[nx][st<<]=dp[nw][st];
}printf("%d\n",ans);
}

毒瘤巅峰的压行巅峰

游览计划

插头dp的话不是很好做,开5种插头记录联通块就行了。

我没有这么写,我写的是最小斯坦纳树。

好像没听过很高端?实际上就是dp。

dp[i][j][st]表式包含(i,j)这个点的一个联通块所覆盖的景点集合为st(状态压缩)。

考虑转移:

首先如果(i,j)就是景点,编号为k,那么dp[i][j][k]=0;

这个点往四周扩展:dp[x][y][st]=min(dp[i][j][st]+w[x][y])

这个点的子集合并:dp[i][j][st]=min(dp[i][j][s1]+dp[i][j][s2]-w[i][j]),其中s1与s2的并集为st。

没了。

但是第一个转移出环了。用原来B组题里的那个SPFA解决循环dp就好了。

记录转移点回溯输出方案。

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int xx[]={,,,-},yy[]={,-,,};
#define tx x+xx[i]
#define ty y+yy[i]
int w[][],n,m,k=,dp[][][],pre[][][],qx[],qy[],iq[][],v[][];
void SPFA(int st,int t=){
for(int i=;i<=n;++i)for(int j=;j<=m;++j)if(dp[i][j][st]<)qx[++t]=i,qy[t]=j,iq[i][j]=;
for(int h=,x,y;x=qx[h],y=qy[h],iq[x][y]=,h<=t;++h)for(int i=;i<;++i)
if(tx&&ty&&tx<=n&&ty<=m&&dp[tx][ty][st]>dp[x][y][st]+w[tx][ty]){
dp[tx][ty][st]=dp[x][y][st]+w[tx][ty];pre[tx][ty][st]=x<<|y<<|st;
if(!iq[tx][ty])iq[qx[++t]=tx][qy[t]=ty]=;
}
}
void dfs(int x,int y,int st){
v[x][y]=;int px=pre[x][y][st]>>,py=pre[x][y][st]>>&,pst=pre[x][y][st]&;
if(!pre[x][y][st])return;
dfs(px,py,pst);if(x==px&&y==py)dfs(px,py,st^pst);
}
int main(){
scanf("%d%d",&n,&m);memset(dp,0x3f,sizeof dp);
for(int i=;i<=n;++i)for(int j=;j<=m;++j)scanf("%d",&w[i][j]);
for(int i=;i<=n;++i)for(int j=;j<=m;++j)if(!w[i][j])dp[i][j][k]=,k<<=;
for(int st=;st<k;++st){
for(int i=;i<=n;++i)for(int j=;j<=m;++j)for(int s=st&st-;s;s=s-&st)
if(dp[i][j][st]>dp[i][j][s]+dp[i][j][st^s]-w[i][j])
dp[i][j][st]=dp[i][j][s]+dp[i][j][st^s]-w[i][j],pre[i][j][st]=i<<|j<<|s;
SPFA(st);
}
for(int i=;i<=n;++i)for(int j=;j<=m;++j)if(!w[i][j]){
dfs(i,j,k-);printf("%d\n",dp[i][j][k-]);
for(int i=;i<=n;++i,puts(""))for(int j=;j<=m;++j)putchar(w[i][j]?(v[i][j]?'o':'_'):'x');
return ;
}
}

难写所以没压行

[专题总结]初探插头dp的更多相关文章

  1. 初探 插头DP

    因为这题,气得我火冒三丈! 这数据是不是有问题啊!我用cin代替scanf后居然就AC了(本来一直卡在Test 18)!导致我调(对)试(排)了一个小时!! UPD:后来细细想想,会不会是因为scan ...

  2. 初探插头dp

    开学那个月学了点新东西,不知道还记不记得了,mark一下 感觉cdq的论文讲的很详细 题主要跟着kuangbin巨做了几道基础的 http://www.cnblogs.com/kuangbin/arc ...

  3. 插头dp初探

    问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...

  4. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  5. 插头dp练习

    最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...

  6. 插头dp

    插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...

  7. HDU 4113 Construct the Great Wall(插头dp)

    好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...

  8. HDU 4949 Light(插头dp、位运算)

    比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...

  9. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

随机推荐

  1. 插入排序 C&&C++

    (blog主要用于展示算法流程) 插入排序算法:通过对未排序的数据逐个插入合适的位置而完成排序工作       流程: (1)先对数组前两个数据进行从小到大排序 (2)将第三个数据与前两个数据比较,将 ...

  2. Python的re模块,正则表达式书写方法

    Python的re模块,正则表达式 #导入re模块 import  re 1.match方法的使用: result = re.match(正则表达式,待匹配的字符串) 正则表达式写法: 第一部分: 字 ...

  3. 基于JavaScript google map集成流程

    google地图集成流程 一.获取Google Map API密钥 1.进入Google官网 => https://www.google.com.hk/ ,申请一个谷歌账号(如果没有)然后访问下 ...

  4. LeetCode 1290. 二进制链表转整数

    地址 https://www.acwing.com/solution/LeetCode/content/7132/ 题目描述给你一个单链表的引用结点 head.链表中每个结点的值不是 0 就是 1.已 ...

  5. poj 3241 Object Clustering (曼哈顿最小生成树)

    Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2640   Accepted: 806 ...

  6. 《Dotnet9》系列-开源C# Winform控件库强力推荐

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  7. LeetCode刷题总结-树篇(中)

    本篇接着<LeetCode刷题总结-树篇(上)>,讲解有关树的类型相关考点的习题,本期共收录17道题,1道简单题,10道中等题,6道困难题. 在LeetCode题库中,考察到的不同种类的树 ...

  8. Maven使用教程三:maven的生命周期及插件机制详解

    前言 今天这个算是学习Maven的一个收尾文章,里面内容不局限于标题中提到的,后面还加上了公司实际使用的根据profile配置项目环境以及公司现在用的archetype 模板等例子. 后面还会总结一个 ...

  9. public class 和 class的区别

    问题:public class 和 class的区别 public class 公共类 class 普通类 一个java源文件中可以有多个class,但是最多只能有一个public class 可以没 ...

  10. C#中提示:当前上下文中不存在名称“ConfigurationManager”

    场景 想要在程序中获取App.config中设置的内容. 想要通过 ConfigurationManager.AppSettings[key]; 来进行获取,已经添加 using System.Con ...