[专题总结]初探插头dp
彻彻底底写到自闭的一个专题。
就是大型分类讨论,压行+宏定义很有优势。
常用滚动数组+哈希表+位运算。当然还有轮廓线。
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的更多相关文章
- 初探 插头DP
因为这题,气得我火冒三丈! 这数据是不是有问题啊!我用cin代替scanf后居然就AC了(本来一直卡在Test 18)!导致我调(对)试(排)了一个小时!! UPD:后来细细想想,会不会是因为scan ...
- 初探插头dp
开学那个月学了点新东西,不知道还记不记得了,mark一下 感觉cdq的论文讲的很详细 题主要跟着kuangbin巨做了几道基础的 http://www.cnblogs.com/kuangbin/arc ...
- 插头dp初探
问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- 插头dp练习
最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...
- 插头dp
插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- HDU 4949 Light(插头dp、位运算)
比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
随机推荐
- 《项目实战》从Spring开始说起
引导 从今天开始,我们正式进入项目实战系列,我们会从项目架构的搭建,以及如何解决三高问题(高并发.高可用.高性能),源码会同步进行更新,欢迎大家持续关注 https://gitee.com/liupa ...
- SpringBoot学习【一】----- HelloWord
springboot是什么 Spring Boot可以轻松创建可以运行的独立的,生产级的基于Spring的应用程序. 大多数Spring Boot应用程序只需要很少的Spring配置. 提供了一个运行 ...
- 【Webpack】373- 一看就懂之 webpack 高级配置与优化
本文原载于 SegmentFault 社区专栏 前海拾贝 作者:JS_Even_JS 一.打包多页面应用 所谓打包多页面,就是同时打包出多个 html 页面,打包多页面也是使用 html-webpac ...
- 【HTTP】HTTP 的15个常见知识点复习
前言 自从入职新公司到现在,我们前端团队内部一直在做 ?每周一练 的知识复习计划,我之前整理了一个 每周一练 之 数据结构与算法 学习内容,大家也快去看看~~ 最近三周,主要复习 网络基础 相关的知识 ...
- org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'taglib' not found
tomcat7,部署tomcat6下的项目统,报tomcat 7: IllegalArgumentException: taglib definitionnotconsistentwithspecif ...
- Ubuntu上面安装sqlite3可视化数据库软件
.介绍:sqlite 3是linux上的小巧的数据库,一个文件就是一个数据库. 2.安装:要安装sqlite 3,可以在终端提示符后运行下列命令: sudo apt-get install sqlit ...
- matplotlib可视化最全指南
1. 折线图:plt.plot 设置数据:plt.plot(x,y),单列数据传入默认y轴,此时x轴数据默认从0逐渐对应递增 设置颜色:plt.plot(x,y,color/c=" &quo ...
- 《Java练习题》习题集四
编程合集: https://www.cnblogs.com/jssj/p/12002760.html Java总结:https://www.cnblogs.com/jssj/p/11146205.ht ...
- skyline加载arcgis发布的wms服务
function AddWMSLayer(LayerName) {var _WMSUrl =“http://10.0.4.141:6080/arcgis/services/poss1/MapServe ...
- Sqlite—查询语句(Select)
基本语法如下 sqlite> select * from tb_user; sqlite> select userid,username from tb_user; 格式化的查询输出 sq ...