插头dp模板(简单路径+一条回路+广义路径)
2015-10-04 19:07
411 查看
#include<cstdio> #include<algorithm> #include<cstring> #define Ms(a,x) memset(a,x,sizeof(a)) /* 插头dp模板 1.解决1条简单路径问题 2.本模板使用括号表示法,hash使用链表 4.输入的为地图权值,输出的为一条简单路径可以得到的最大权值(有障碍,路可以不走) 5.记得当状态表示的太大时code的类型要改为longlong */ using namespace std; typedef long long Int; const int Hashsize=10007; const int Maxstate=15000; int n,m; int Map[12][12]; Int ans; inline void up(Int &x,Int y) { if(y>x)x=y; } void input() { scanf("%d%d",&n,&m); ans=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&Map[i][j]),up(ans,Map[i][j]); } inline int get(int code,int y) { return code>>2*y&3; } inline int shift(int x,int y) { return x<<2*y; } struct Hash { int state[Maxstate],head[Hashsize],nxt[Maxstate]; Int w[Maxstate]; int tot; void init() { Ms(head,-1); tot=0; } void insert(int x,Int y) { int t=x%Hashsize; for(int i=head[t];~i;i=nxt[i]) if(state[i]==x) { up(w[i],y); return; } nxt[tot]=head[t]; head[t]=tot; w[tot]=y; state[tot++]=x; } void pt()//debug专用 { printf("tot=%d\n",tot); for(int i=0;i<tot;i++) { for(int j=0,t=state[i];j<=m+1;j++,t>>=2) printf("%3d ",t&3); printf("w=%lld\n",w[i]); }puts(""); } }h[2]; void modify(int &code,int loc,int tar,int dir,int ned) { int incode[13],i,t; for(i=0,t=code;i<=m;i++,t>>=2) incode[i]=t&3; int cnt=0; for(i=loc;;i+=dir) if(incode[i]==ned) { if(!cnt){code+=(tar-get(code,i))*shift(1,i);return;} cnt--; } else if(incode[i]==3-ned)cnt++; } void dp(int cs,int x,int y) { for(int i=0;i<h[cs].tot;i++) { int code=h[cs].state[i]; //printf("%d %d %d\n",code,x,y); int dep=get(code,m+1); Int w=h[cs].w[i]+Map[x][y]; if(x&&!y) { code-=shift(dep,m+1); code<<=2;code+=shift(dep,m+1); } int left=get(code,y),up=get(code,y+1); if(!Map[x][y]) { if(!left&&!up)h[cs^1].insert(code,w); continue; } if(left&&up) { code-=shift(left,y)+shift(up,y+1); if(left==3&&up==3) { h[cs^1].insert(code,w); continue; } if(left==3||up==3) { int di,ned; if(left==3)ned=up; else ned=left; di=ned==1?1:-1; modify(code,left==3?y+1:y,3,di,3-ned);//code,loc,tar,dir,ned h[cs^1].insert(code,w); continue; } if(left==up) { modify(code,left==1?y+1:y,left,left==1?1:-1,3-left); h[cs^1].insert(code,w); continue; } if(left==2&&up==1) { h[cs^1].insert(code,w); continue; } continue; } if(!left&&!up) { if(x<n-1&&y<m-1) h[cs^1].insert(code+shift(1,y)+shift(2,y+1),w); if(dep<2) { if(x<n-1)h[cs^1].insert(code+shift(3,y)+shift(1,m+1),w); if(y<m-1)h[cs^1].insert(code+shift(3,y+1)+shift(1,m+1),w); } h[cs^1].insert(code,w-Map[x][y]); continue; } if(left&&!up) { if(dep<2) { int code1=code; code1+=shift(1,m+1)-shift(left,y); if(left==1)modify(code1,y,3,1,2); else if(left==2)modify(code1,y,3,-1,1); h[cs^1].insert(code1,w); } if(x<n-1)h[cs^1].insert(code,w); if(y<m-1)h[cs^1].insert(code-shift(left,y)+shift(left,y+1),w); continue; } if(!left&&up) { if(dep<2) { int code1=code; code1+=shift(1,m+1)-shift(up,y+1); if(up==1)modify(code1,y+1,3,1,2); else if(up==2)modify(code1,y+1,3,-1,1); h[cs^1].insert(code1,w); } if(y<m-1)h[cs^1].insert(code,w); if(x<n-1)h[cs^1].insert(code-shift(up,y+1)+shift(up,y),w); continue; } } } void solve() { int cs=0; //int all=0; h[0].init(); h[0].insert(0,0); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { h[cs^1].init(); dp(cs,i,j); cs^=1; //debug专用 //printf("转移完%d %d\n",i,j); //h[cs].pt(); // all=max(all,h[cs].tot); } for(int i=0;i<h[cs].tot;i++) up(ans,h[cs].w[i]); printf("%lld\n",ans); } int main() { int T; scanf("%d",&T); while(T--) { input(); solve(); } return 0; }
/* 插头dp模板 1.解决全图为一条回路,有障碍 2.括号匹配:0:无插头,1:左插头,2:右插头 3.极限数据12 12 无障碍:1076226888605605706 */ #include<bits/stdc++.h> using namespace std; const int Hashsize=10007; typedef long long Int; int n,m,ex,ey;//ex,ey为最后一个非障碍格 bool Map[12][12]; char s[12]; void input() { for(int i=0;i<n;i++) { scanf("%s",s);//比如把这句注释了,输入12 12,应该得到1076226888605605706 for(int j=0;j<m;j++)Map[i][j]=s[j]=='#'?1:0; } ex=n-1,ey=m-1; } struct Hash { vector<int>state,nxt; vector<Int>w; int head[Hashsize]; int tot; void init() { memset(head,-1,sizeof(head)); tot=0; state.clear(); nxt.clear(); w.clear(); } void insert(int x,Int y) { int t=x%Hashsize; for(int i=head[t];i!=-1;i=nxt[i]) { if(state[i]==x) { w[i]+=y; return; } } nxt.push_back(head[t]); state.push_back(x); w.push_back(y); head[t]=tot++; } }h[2]; inline int get(int code,int y) { return code>>2*y&3; } inline int shift(int x,int y) { return x<<2*y; } void modify(int &code,int loc,int pace) { int ned=pace>0?2:1; int incode[13]; for(int i=0,t=code;i<=m;i++,t>>=2) incode[i]=t&3; int cnt=0; for(int i=loc;;i+=pace) { if(incode[i]==ned) { if(!cnt){code-=pace*shift(1,i);return;} cnt--; } else if(incode[i])cnt++; } } void dp(int cs,int x,int y)//记得设置ex,ey { if(Map[x][y]) { for(int i=0;i<h[cs].tot;i++) { int code=h[cs].state[i]; if(x&&!y)code<<=2; int left=get(code,y),up=get(code,y+1); if(!left&&!up)h[cs^1].insert(code,h[cs].w[i]); } return; } for(int i=0;i<h[cs].tot;i++) { int code=h[cs].state[i]; Int w=h[cs].w[i]; if(x&&!y)code<<=2; int left=get(code,y),up=get(code,y+1); if(left&&up) { code-=shift(left,y)+shift(up,y+1); if(left!=up) { if((x==ex&&y==ey)||left==2) h[cs^1].insert(code,w); continue; } if(left==1) { modify(code,y+2,1); h[cs^1].insert(code,w); continue; } if(left==2) { modify(code,y-1,-1); h[cs^1].insert(code,w); continue; } } if(left&&!up) { if(x<n-1)h[cs^1].insert(code,w); if(y<m-1)h[cs^1].insert(code-shift(left,y)+shift(left,y+1),w); continue; } if(up&&!left) { if(y<m-1)h[cs^1].insert(code,w); if(x<n-1)h[cs^1].insert(code-shift(up,y+1)+shift(up,y),w); } if(!left&&!up&&x<n-1&&y<m-1) h[cs^1].insert(code+shift(1,y)+shift(2,y+1),w); } } void solve() { int cs=0; h[0].init(); h[0].insert(0,1); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { printf("i=%d j=%d\n",i,j); printf("tot=%d\n",h[cs].tot); h[cs^1].init(); dp(cs,i,j); cs^=1; } } Int ans=0; for(int i=0;i<h[cs].tot;i++) ans+=h[cs].w[i]; printf("%lld\n",ans); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { input(); solve(); } }
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define Ms(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long Int; const int Hashsize=10007,Maxstate=15000; char Map[9][9]; char ch[]={'o','#'}; int pre[9][9][Maxstate]; int pe[9][9][Maxstate]; int n,m; /* 原题 uva10572 广义路径 题意:棋盘只能涂黑白,黑白各自联通,不能有2*2的方块涂有相同的颜色,要求输出方案数和其中一种方案 */ inline int shift(int x,int y) { return x<<y; } inline int get(int x,int y) { return x>>y&1; } struct Hash { int head[Hashsize]; int nxt[Maxstate],state[Maxstate],col[Maxstate]; Int w[Maxstate]; int tot; void init() { tot=0; Ms(head,-1); } void insert(int st,int cl,Int ww,int x,int y,int pst,int cs) { int t=((st<<5)+cl)%Hashsize; for(int i=head[t];~i;i=nxt[i]) if(state[i]==st&&col[i]==cl) { w[i]+=ww; pre[x][y][i]=pst; pe[x][y][i]=cs; return; } nxt[tot]=head[t]; head[t]=tot; state[tot]=st,col[tot]=cl,w[tot]=ww; pe[x][y][tot]=cs; pre[x][y][tot++]=pst; } //for debug void pt() { printf("tot=%d\n",tot); for(int i=0;i<tot;i++) { printf("state= "); for(int j=0,k=state[i];j<m;j++,k>>=3) printf("%3d",k&7); puts(""); printf("col= "); for(int j=0,k=col[i];j<m+3;j++,k>>=1) printf("%3d",k&1); puts(""); printf("w=%lld\n",w[i]); puts(""); } } }h[2]; int code[10]; void decode(int cd) { for(int i=0;i<m;i++,cd>>=3) code[i]=cd&7; } int encode() { int ref[10],cnt=0; Ms(ref,-1); for(int i=0;i<m;i++) { if(ref[code[i]]<0) ref[code[i]]=cnt++; code[i]=ref[code[i]]; } int ret=0; for(int i=m-1;i>=0;i--) ret=(ret<<3)+code[i]; return ret; } bool check(int y,int st) { for(int i=st;i<m;i++) if(i!=y&&code[i]==code[y]) return true; return false; } void modify(int loc,int x) { int t=code[loc]; for(int i=0;i<m;i++) if(code[i]==t) code[i]=x; } void dp(int cs,int x,int y,int cl) { if(Map[x][y]!='.'&&Map[x][y]!=ch[cl])return; //col的第0-m位表示格子的颜色,m+1-m+2表示是否只能使用一种颜色10只能用白色,11只能用黑色 for(int i=0;i<h[cs].tot;i++) { int col=h[cs].col[i],st=h[cs].state[i]; int last=col>>(m+1); col-=last<<(m+1); if(x&&!y) { col=col&shift(1,m)-1; col<<=1; } //ul,ur,dl分别表示左上、右上、左下的格子的颜色 int ul=0,ur=0,dl=0; if(x){ul=get(col,y);ur=get(col,y+1);} if(y)dl=get(col,y-1); //这四个格子颜色不能全部相同 if(x&&y&&dl==ul&&ul==ur&&ul==cl) continue; //如果后面的格子只能使用一种颜色但与当前使用的不同,则不合法 if(last&&(last&1)!=cl)continue; col+=(cl-ul)*shift(1,y); //解码 decode(st); //考虑一些联通分量消失的格子,如果他们所处的联通分量消失了,则后面只能涂一种颜色 bool flag=false; if(x&&ur!=cl&&!check(y,x==n-1?y+1:0)) { if(last)continue; flag=true; } if(x==n-1&&y&&!last&&dl!=cl&&!check(y-1,y+1)) { if(last)continue; if(flag&&code[y-1]!=code[y])continue; flag=true; } if(flag)last=2+cl; col+=last<<(m+1); //重新编码+最小表示 if(y&&cl==dl)modify(y-1,9); if(x&&ur==cl)modify(y,9); code[y]=9; h[cs^1].insert(encode(),col,h[cs].w[i],x,y,i,cl); } } vector<int>bef; void solve() { int cs=0; h[cs].init(); h[cs].insert(0,0,1,0,0,0,0); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { h[cs^1].init(); for(int k=0;k<2;k++) dp(cs,i,j,k); cs^=1; //printf("转移完%d %d\n",i,j);h[cs].pt(); } Int ans=0; int last=-1; bef.clear(); for(int i=0;i<h[cs].tot;i++) { if(h[cs].w[i]) ans+=h[cs].w[i],last=i,bef.push_back(i); } if(!ans)puts("0\n"); else {//for debug /*for(int k=0;k<bef.size();k++) { int st=bef[k]; for(int i=n-1;i>=0;i--) for(int j=m-1;j>=0;st=pre[i][j][st],j--) Map[i][j]=pe[i][j][st]?'#':'o'; for(int i=0;i<n;i++) printf("%s\n",Map[i]); puts(""); }*/ printf("%lld\n",ans); for(int i=n-1;i>=0;i--) for(int j=m-1;j>=0;last=pre[i][j][last],j--) Map[i][j]=pe[i][j][last]?'#':'o'; for(int i=0;i<n;i++) printf("%s\n",Map[i]); puts(""); } } void input() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",Map[i]); } int main() { int T; scanf("%d",&T); while(T--) { input(); solve(); } return 0; }
相关文章推荐
- HDU2608-0 or 1(数论+找规律)
- Flex SDK bin命令解析–mxmlc参数列表
- Flex SDK bin命令解析–mxmlc参数列表
- 国庆随笔
- Jquery给easyui的表单元素赋值,获取值
- Linux 学习笔记 常用命令
- hadoop学习笔记之分布式计算框架
- [PAT]1097. Deduplication on a Linked List (25)
- 50 Pow(x, n)
- 连接打开
- 76. Minimum Window Substring (String, Map)
- hdu 4018 Parsing URL
- JavaBean
- 【AMPPZ2014】【BZOJ4143】The Lawyer
- codeforces 582A. GCD Table 解题报告
- HDU5496求整数序列的子串的并集和,map的简单使用
- LA 2038 Strategic game(最小点覆盖,树形dp,二分匹配)
- Codeforces Round #323 (Div. 2) 583A. Asphalting Roads
- 条款31提及pimpl设计模式
- UIPickerView控件的使用