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);}}


原创粉丝点击