您的位置:首页 > 其它

HDU 3377 插头dp

2015-08-14 18:51 295 查看
题目大意:

从左上角走到右下角,每个点之多经过一次,取到所有路径上经过点的权值,求最大的权值之和,这里走到右下角就算停止了

这里有个思路是转化成熟悉的回路问题

在上方和右方最外围定义一圈权值为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: