HDU 3377 Plan 解题报告(插头DP)
来源:互联网 发布:手机淘宝怎样修改星评 编辑:程序博客网 时间:2024/05/01 05:12
解题报告:刚开始时卡了一下,以为用0,1表示插头即可,终点处判断有一个1插头就更新答案。后来想了一下,非起点到终点的部分可能成环,而结果也会被加进去。
如下图:
所以还是用以前Ural1519 的方法,使用括号序列。如果发现左插头为1,上插头为2,则放弃该状态。右下角如果有左插头亦或上插头,更新答案。
如果不会插头DP,可以看我的上一篇博客:插头DP入门。
代码如下:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100013;int now,pre;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+1)%maxn;if( ~H[s] ){N[H[s]]=max(N[H[s]],num);return ;}S[size]=SS;N[size]=num;H[s]=size++;}} dp[2];int maze[10][10];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 main(){int m,n;int cas=1;while(~scanf("%d%d",&n,&m)){for(int i=0;i<n;i++) for(int j=0;j<m;j++)scanf("%d",&maze[i][j]);now=1;pre=0;dp[now].init();dp[now].push(1,0);int ans=(1<<31);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){dp[now].push(S,num);set(S,j,1);set(S,j+1,2);if(i<n-1 && j<m-1)dp[now].push(S,num+maze[i][j]);}else if((p>0) ^ (q>0)){if(i==n-1 && j==m-1){set(S,j,0);set(S,j+1,0);if(S==0)ans=max(ans,num+maze[i][j]);continue;}if(i+(p>0)<n && j+(q>0)<m)dp[now].push(S,num+maze[i][j]);set(S,j,q);set(S,j+1,p);if(i+(q>0)<n && j+(p>0)<m)dp[now].push(S,num+maze[i][j]);}else if(p==2 && q==1){set(S,j,0);set(S,j+1,0);dp[now].push(S,num+maze[i][j]);}else if(p==1 && q==2){}else if(p==1 && q==1){int find=1;for(int k=j+2;k<=m;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,1);dp[now].push(S,num+maze[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==2)find++;else if(v==1)find--;if(find==0){set(S,j,0);set(S,j+1,0);set(S,k,2);dp[now].push(S,num+maze[i][j]);break;}}}}}for(int s=0;s<dp[now].size;s++)dp[now].S[s]<<=2;}printf("Case %d: %d\n",cas++,ans);}}
最小表示法:
#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 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]]=max(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=maze[i][j];if(ma==0){dp[now].push(encode(),num);if(i<n-1 && j<m-1){code[j]=code[j+1]=13;dp[now].push(encode(),num+val);}}else if(mi==0){if(i<n-1){code[j]=ma;code[j+1]=0;dp[now].push(encode(),num+val);}if(j<m-1){code[j]=0;code[j+1]=ma;dp[now].push(encode(),num+val);}if(i==n-1 && j==m-1){code[j]=0;code[j+1]=0;if(encode()==0) ans=max(ans,num+val);}}else if(left==up){}else{code[j]=code[j+1]=0;merge(left,up);dp[now].push(encode(),num+val);}}}void solve(){now=1,pre=0;ans=(1<<31);dp[now].init();dp[now].push(1,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(){memset(maze,0,sizeof(maze));for(int i=0;i<n;i++)for(int j=0;j<m;j++)scanf("%d",&maze[i][j]);}int main(){int cas=1;while(~scanf("%d%d",&n,&m)){init();solve();printf("Case %d: %d\n",cas++,ans);}}
- HDU 3377 Plan 解题报告(插头DP)
- hdu 3377 Plan(插头dp)
- hdu 3377 Plan 插头dp
- HDU 1964 Pipes 解题报告(插头DP)
- HDU 4285 circuits 解题报告(插头DP)
- hdu 1964 Plan (插头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)
- HDU3377 Plan 插头dp
- HDU 4671 Backup Plan 解题报告
- ZOJ 3256 Tour in the Castle 解题报告(插头DP)
- hdu 1024 dp 解题报告
- hdu 1964(插头DP一条回路)
- HDU 4804 Campus Design(插头DP)
- hdu 1693 插头dp
- 如何解决SVN Commit failed (details follow): Access denied
- java求阶乘和,n的重要性,犯了致命错误。
- 记录一下PHP数组数据分页的方法 array_slice() 函数的使用
- C程序语言strstr函数分析和使用
- 关于程序用途的小见解
- HDU 3377 Plan 解题报告(插头DP)
- java读取配置文件里的信息
- JBOSS优化
- thinksns
- linux中遇到的问题
- Blocks from Wiki
- 程序员实践经验
- JAVA学习笔记一:JAVA基础JAVA SE
- 黑马程序员_String 对象