HDU 3377 插头dp
2015-08-14 18:51
295 查看
题目大意:
从左上角走到右下角,每个点之多经过一次,取到所有路径上经过点的权值,求最大的权值之和,这里走到右下角就算停止了
这里有个思路是转化成熟悉的回路问题
在上方和右方最外围定义一圈权值为0 , 那么我们相当于从定义以后的左上角开始经过所有外围点形成的回路,那么去掉最外围的0,剩下的就是(1,1)-》(n,n)的权值和了
但是这里最外围的点的插头具有特殊性,每次到最外围的点,你左和上有且仅有一个插头,而且出去的方向必然是下一个最外围的点
从左上角走到右下角,每个点之多经过一次,取到所有路径上经过点的权值,求最大的权值之和,这里走到右下角就算停止了
这里有个思路是转化成熟悉的回路问题
在上方和右方最外围定义一圈权值为0 , 那么我们相当于从定义以后的左上角开始经过所有外围点形成的回路,那么去掉最外围的0,剩下的就是(1,1)-》(n,n)的权值和了
但是这里最外围的点的插头具有特殊性,每次到最外围的点,你左和上有且仅有一个插头,而且出去的方向必然是下一个最外围的点
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define ll long long const int HASH = 10007; const int STATE = 1000010; const int MAXD = 15; int n , m; int code[MAXD] , mp[MAXD][MAXD]; bool flag[MAXD][MAXD];//标记位,标记当前点能否作为最终点 ll ans = 0; int w[MAXD][MAXD]; struct HASHMAP{ int head[HASH] , next[STATE] , state[STATE] , size; ll f[STATE]; void init(){ size = 0; memset(head , -1 , sizeof(head)); } void push_in(int st , ll sum){ int h = st%HASH; for(int i = head[h] ; ~i ; i=next[i]){ if(st == state[i]){ f[i]=max(f[i] , sum); //这题目为求最大值 return ; } } f[size]=sum; state[size] = st; next[size] = head[h]; head[h] = size++; } }hashmap[2]; int num = 0;//记录共有的插头数量 void decode(int *code , int m , int st) { num = 0; for(int i=m ; i>=0 ; i--){ code[i] = st&3; st>>=2; if(code[i]) num++; } } int encode(int *code , int m) { int st=0; for(int i=0 ; i<=m ; i++){ st<<=2; st |= code[i]; } return st; } void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧 { for(int i=m ; i>=0 ; i--) code[i] = code[i-1]; code[0] = 0; } void dpblank(int i , int j , int cur) { int k , left , up; for(k=0 ; k<hashmap[cur].size ; k++){ decode(code , m , hashmap[cur].state[k]); left = code[j-1]; up = code[j]; if(!left && !up){ if(mp[i][j]==2) continue; if(mp[i][j]==1){ if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); } if(mp[i][j+1] && mp[i+1][j]){ code[j-1] = 1 , code[j] = 2; hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } } else if(!left && up){ if(mp[i][j]==2 && (up!=2)) continue; else if(mp[i][j]==2){ if(mp[i][j+1]==2) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); else{ code[j-1] = up , code[j] = 0; if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } continue; } if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); if(mp[i+1][j]){ code[j-1] = up , code[j] = 0; if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } } else if(left && !up){ if(mp[i][j]==2 && (left!=2)) continue; else if(mp[i][j]==2){ if(mp[i][j+1]==2){ code[j-1] = 0 , code[j] = left; hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); }else{ if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } continue; } if(mp[i+1][j]){ if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } if(mp[i][j+1]){ code[j-1] = 0 , code[j] = left; hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } } else if(mp[i][j]==2) continue; else if(left==1 && up == 1){ int cnt = 1; for(int v=j+1 ; v<=m ; v++){ if(code[v]==1)cnt++; if(code[v]==2)cnt--; if(!cnt){ code[v]=1; break; } } code[j-1] = code[j] = 0; if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } else if(left == 2 && up == 2){ int cnt=1; for(int v=j-2 ; v>=1 ; v--){ if(code[v]==2)cnt++; if(code[v]==1)cnt--; if(!cnt){ code[v]=2; break; } } code[j-1] = code[j] = 0; if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } else if(left==1 && up==2){ if(i==n && j==m) ans=max(ans,hashmap[cur].f[k]+w[i][j]); } else{ code[j-1]=code[j]=0; if(j == m) shift(code , m); hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]+w[i][j]); } } } void init() { for(int i=1 ; i<=m+1 ; i++) mp[1][i]=2 , w[1][i] = 0; for(int i=2 ; i<=n+1 ; i++){ for(int j=1 ; j<=m ; j++) scanf("%d" , &w[i][j]) , mp[i][j]=1; w[i][m+1] = 0 , mp[i][m+1] = 2; mp[i][m+2] = mp[n+2][i]=0; } n++ , m++; mp[1][1] = mp [m] = 1; /*for(int i=1 ; i<=n ; i++){ for(int j=1 ;j <=m ; j++){ cout<<mp[i][j]<<" "; } cout<<endl; }*/ } ll solve() { ans = -1e9; int cur = 0; hashmap[cur].init(); hashmap[cur].push_in(0 , 0); for(int i=1 ; i<=n ; i++){ for(int j=1 ; j<=m ; j++){ hashmap[cur^1].init(); dpblank(i , j , cur); cur ^= 1; /* cout<<"test: "<<i<<" "<<j<<endl; for(int k=0 ; k<hashmap[cur].size ; k++) cout<<hashmap[cur].f[k]<<endl;*/ } } // for(int i=0 ; i<hashmap[cur].size ; i++) return ans; } int main() { // freopen("in.txt" , "r" , stdin); int cas = 0; while(~scanf("%d%d" , &n , &m)) { init(); printf("Case %d: ",++cas); if(n==1 && m==1){ printf("%d\n" , w[1][1]); continue; } printf("%I64d\n" , solve()); } return 0; }
相关文章推荐
- No package mysql-server available.
- Nginx模块开发(5)————开发简单的HTTP过滤模块
- MySQL5.6安装步骤(windows7/8_64位)
- Ubuntu下git使用
- APK 代码混淆
- poj2367
- 一致性哈希算法及其在分布式系统中的应用
- java:关于字符编码的试题
- 图论500题
- 图论500题
- 编写高质量代码改善C#程序的157个建议——建议23:避免将List<T>作为自定义集合类的基类
- mysql 插入去重,以及设置联合唯一索引问题
- FMDB简单应用
- 4.2 虚拟成员函数
- servlet
- DroidBox 环境搭建 【图文】
- 使用fis对资源进行打包、压缩、合并、加MD5发布
- js中的"=="和equals()以及is()三者的区别
- LeetCode:Find Minimum in Rotated Sorted Array
- 浅谈数据结构系列 栈和队列