HDU 1964 Pipes 解题报告(插头DP)
来源:互联网 发布:超级基因优化液百科 编辑:程序博客网 时间:2024/05/16 10:34
插头DP。格子间有value,求哈密顿回路value和最小。和Ural 1519类似,给每个状态更新最小的value值即可。
代码如下:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=59999;struct Node{ int H[maxn]; int S[maxn]; int N[maxn]; int size; void init() { size=0; memset(H,-1,sizeof(H)); } void push(int SS,int num) { int s=SS%maxn; while( ~H[s] && S[H[s]]!=SS ) { s++; s%=maxn; } if(~H[s]) { N[H[s]]=min(N[H[s]],num); return; } N[size]=num; S[size]=SS; H[s]=size++; } int get(int SS) { int s=SS%maxn; while( ~H[s] && S[H[s]]!=SS) { s++; s%=maxn; } if(~H[s]) return N[H[s]]; else return 0; }} dp[2];int now,pre;int get(int S,int p,int l=2){ return (S>>(p*l))&((1<<l)-1);}void set(int &S,int p,int v,int l=2){ S^=get(S,p,l)<<(p*l); S^=(v&((1<<l)-1))<<(p*l);}int a[12][12];int b[12][12];int maze[12][12];int main(){int T;scanf("%d",&T);while(T--){int ans=~0U>>2;int n,m;scanf("%d%d%*c",&n,&m);memset(maze,0,sizeof(maze));for(int i=0;i<n;i++)for(int j=0;j<m;j++)maze[i][j]=1;char str[1000];gets(str);memset(a,0,sizeof(a));memset(b,0,sizeof(b));for(int i=1;i<n;i++){gets(str);for(int j=1;j<m;j++)a[i-1][j]=str[j*2]-'0';gets(str);for(int j=0;j<m;j++)b[i][j]=str[j*2+1]-'0';}gets(str);for(int j=1;j<m;j++)a[n-1][j]=str[j*2]-'0';gets(str);now=1;pre=0;dp[now].init();dp[now].push(0,0);for(int i=0;i<n;i++){for(int j=0;j<m;j++){swap(now,pre);dp[now].init();for(int s=0;s<dp[pre].size;s++){int S=dp[pre].S[s];int num=dp[pre].N[s];int p=get(S,j);int q=get(S,j+1);if(p==0 && q==0){set(S,j,1);set(S,j+1,2);if(maze[i][j+1] && maze[i+1][j])dp[now].push(S,num);}else if(p>0 && q==0){if(maze[i+1][j])dp[now].push(S,num+a[i][j]);set(S,j,0);set(S,j+1,p);if(maze[i][j+1])dp[now].push(S,num+a[i][j]);}else if(p==0 && q>0){if(maze[i][j+1])dp[now].push(S,num+b[i][j]);set(S,j,q);set(S,j+1,0);if(maze[i+1][j])dp[now].push(S,num+b[i][j]);}else if(p==1 && q==1){int find=1;for(int k=j+2;k<=m;k++){int v=get(S,k);if(v==2) find--;else if(v==1) find++;if(find==0){set(S,j,0);set(S,j+1,0);set(S,k,1);dp[now].push(S,num+a[i][j]+b[i][j]);break;}}}else if(p==2 && q==2){int find=1;for(int k=j-1;k>=0;k--){int v=get(S,k);if(v==1) find--;else if(v==2) find++;if(find==0){set(S,j,0);set(S,j+1,0);set(S,k,2);dp[now].push(S,num+a[i][j]+b[i][j]);break;}}}else if(p==2 && q==1){set(S,j,0);set(S,j+1,0);dp[now].push(S,num+a[i][j]+b[i][j]);}else if(p==1 && q==2){if(i==n-1 && j==m-1){set(S,j,0);set(S,j+1,0);dp[now].push(S,num+a[i][j]+b[i][j]);}}}}for(int s=0;s<dp[now].size;s++)dp[now].S[s]<<=2;}printf("%d\n",dp[now].get(0));}}
最小表示法:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int maxn=59999;const int L=3;int now,pre;int n,m;int ans;int endx,endy;int maze[15][15];int a[15][15];int b[15][15];int code[15],ch[15];struct Node{int h[maxn];int n[maxn];LL s[maxn];int size;void init(){memset(h,-1,sizeof(h));size=0;}void push(LL ss,int num){int i=ss%maxn;while( ~h[i] && s[h[i]]!=ss )i=(i+1)%maxn;if( ~h[i] ){n[h[i]]=min(n[h[i]],num);}else{s[size]=ss;n[size]=num;h[i]=size++;}}} dp[2];void decode(LL s){for(int i=0;i<=m;i++)code[i]=s&((1<<L)-1),s>>=L;}LL encode(){memset(ch,-1,sizeof(ch));ch[0]=0;LL s=0;int cnt=1;for(int i=m;i>=0;i--){if( ch[code[i]]==-1 ) ch[code[i]]=cnt++;s<<=L;s|=ch[code[i]];}return s;}void shift(){for(int s=0;s<dp[now].size;s++)dp[now].s[s]<<=L;}void merge(int a,int b){for(int i=0;i<=m;i++) if(code[i]==a)code[i]=b;}void doGrid(int i,int j){for(int s=0;s<dp[pre].size;s++){decode(dp[pre].s[s]);int num=dp[pre].n[s];int left=code[j];int up=code[j+1];int ma=max(left,up);int mi=min(left,up);int val=0;if(left) val+=a[i][j];if(up) val+=b[i][j];if(ma==0){if(maze[i][j+1] && maze[i+1][j]){code[j]=code[j+1]=13;dp[now].push(encode(),num);}}else if(mi==0){if(maze[i+1][j]){code[j]=ma;code[j+1]=0;dp[now].push(encode(),num+val);}if(maze[i][j+1]){code[j]=0;code[j+1]=ma;dp[now].push(encode(),num+val);}}else if(left==up){if(i==n-1 && j==m-1){code[j]=0;code[j+1]=0;if(encode()==0) ans=max(ans,num+val);}}else{code[j]=code[j+1]=0;merge(left,up);dp[now].push(encode(),num+val);}}}void solve(){now=1,pre=0;ans=0;dp[now].init();dp[now].push(0,0);for(int i=0;i<n;i++){for(int j=0;j<m;j++){swap(now,pre);dp[now].init();doGrid(i,j);}shift();}}void init(){scanf("%d%d%*c",&n,&m);memset(maze,0,sizeof(maze));for(int i=0;i<n;i++)for(int j=0;j<m;j++)maze[i][j]=1;char str[1000];gets(str);memset(a,0,sizeof(a));memset(b,0,sizeof(b));for(int i=1;i<n;i++){gets(str);for(int j=1;j<m;j++)a[i-1][j]=str[j*2]-'0';gets(str);for(int j=0;j<m;j++)b[i][j]=str[j*2+1]-'0';}gets(str);for(int j=1;j<m;j++)a[n-1][j]=str[j*2]-'0';gets(str);}int main(){int T;int cas=1;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);init();solve();printf("%d\n",ans);}}
- HDU 1964 Pipes 解题报告(插头DP)
- hdu 1964 Pipes 插头DP
- HDU 3377 Plan 解题报告(插头DP)
- HDU 4285 circuits 解题报告(插头DP)
- FZU 1977 Pandora adventure 解题报告(插头DP)
- POJ 1739 Tony's Tour 解题报告(插头DP)
- POJ 3133 Manhattan Wiring 解题报告(插头DP)
- ZOJ 3466 The Hive II 解题报告(插头DP)
- ZOJ 3213 Beautiful Meadow 解题报告(插头DP)
- hdu 1964 插头dp
- hdu 1964(插头DP一条回路)
- hdu 1964 Plan (插头dp)
- ZOJ 3256 Tour in the Castle 解题报告(插头DP)
- hdu 1024 dp 解题报告
- HDU 4804 Campus Design(插头DP)
- hdu 1693 插头dp
- hdu 4064 (插头DP)
- HDU-1693-插头dp
- ORACLE:object_id vs data_object_id
- JNI入门
- 矩阵分解
- 社交网络分析(Social Network Analysis)
- JSP的一些小知识
- HDU 1964 Pipes 解题报告(插头DP)
- ORA-01552: cannot use system rollback segment for non-system tablespace 'USERS'
- WPF: drawing a video using MediaPlayer, VideoDrawing and DrawingBrush
- 代码清单4-1
- 认识JNI
- Find them, Catch them 并查集
- 内核驱动错误
- Windows平台下的多线程编程
- Mysql表的约束设计和关联关系设计