hdu3377之简单路径求最值
来源:互联网 发布:数据噪声 编辑:程序博客网 时间:2024/06/16 11:50
Plan
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 686 Accepted Submission(s): 234
Problem Description
One day, Resty comes to an incredible world to seek Eve -- The origin of life. Lilith, the sister of Eve, comes with him. Although Resty wants to find Eve as soon as possible, Lilith likes to play games so much that you can't make her make any move if you don't play with her.
Now they comes to the magical world and Lilish ask Resty to play with her.
The game is following :
Now the world is divided into a m * n grids by Lilith, and Lilith gives each grid a score.
So we can use a matrix to describe it.
You should come from cell(0, 0) to cell(m-1, n-1) (Up-Left to Down-Right) and try to colloct as more score as possible.
According to Lilish's rule, you can't arrive at each cell more than once.
Resty knows that Lilish will be easy to find the max score, and he doesn't want to lose the game.
So he want to find the game plan to reach the max score.
Your task is to calculate the max score that Lilish will find, the map is so small so it shouldn't be difficult for you, right?
Now they comes to the magical world and Lilish ask Resty to play with her.
The game is following :
Now the world is divided into a m * n grids by Lilith, and Lilith gives each grid a score.
So we can use a matrix to describe it.
You should come from cell(0, 0) to cell(m-1, n-1) (Up-Left to Down-Right) and try to colloct as more score as possible.
According to Lilish's rule, you can't arrive at each cell more than once.
Resty knows that Lilish will be easy to find the max score, and he doesn't want to lose the game.
So he want to find the game plan to reach the max score.
Your task is to calculate the max score that Lilish will find, the map is so small so it shouldn't be difficult for you, right?
Input
The input consists of more than one testdata.
Process to the END OF DATA.
For each test data :
the first live give m and n. (1<=m<=8, 1<=n<=9)
following m lines, each contain n number to give you the m*n matrix.
each number in the matrix is between -2000 and 2000
Process to the END OF DATA.
For each test data :
the first live give m and n. (1<=m<=8, 1<=n<=9)
following m lines, each contain n number to give you the m*n matrix.
each number in the matrix is between -2000 and 2000
Output
Output Format is "Case ID: ANS" one line for each data
Don't print any empty line to the output
Don't print any empty line to the output
Sample Input
2 21 23 13 30 -20 1001 -20 -201 1 1
Sample Output
Case 1: 5Case 2: 61
首先初始化状态即[1,0]的状态为1,表示从[1,0] => [1,1]有一个插头,这样就能保证是从点[1,1]开始然后将点[n+1,m]表示为可经过,然后进行插头DP时从[n,m] => [n+1,m]可以有插头,所以最终也保证了以点[n,m]结束在这个过程中进行插头DP只需要去掉p=1,q=2的情况就行,因为这样会形成环另外还有一种方法是增加外围使得题目变成求回路的最值0 0 0 0 00 # # # 0------1 0 1 |# 01 1 1 |# 0------# # 0 0 0这样增加外围就一定能保证求的回路是如果去掉外围就是从点[1,1]到[n,m]
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <queue>#include <algorithm>#include <map>#include <cmath>#include <iomanip>#define INF 99999999typedef long long LL;using namespace std;const int MAX=30000+10;const int N=10+10;int n,m,size,index;int val[N][N],total[2],bit[N];int head[MAX],next[MAX],Hash[MAX];LL dp[2][MAX],state[2][MAX],sum;void HashCalState(LL s,LL Val){ int pos=s%MAX; for(int i=head[pos];i != -1;i=next[i]){ if(state[index][Hash[i]] == s){ dp[index][Hash[i]]=max(dp[index][Hash[i]],Val); return; } } ++total[index]; state[index][total[index]]=s; dp[index][total[index]]=Val; //头插法 Hash[size]=total[index]; next[size]=head[pos]; head[pos]=size++; }void DP(){ index=0; total[index]=1; state[index][1]=1;//初始化的状态是第一格有一个插头进来(从0进来) dp[index][1]=val[1][1]; sum=-INF; for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ memset(head,-1,sizeof head); size=0; index=index^1; total[index]=0; for(int k=1;k<=total[index^1];++k){ LL s=state[index^1][k]; LL Val=dp[index^1][k]; int p=(s>>bit[j-1])%4; int q=(s>>bit[j])%4; int d=(s>>bit[j+1])%4; if(!p && !q){ HashCalState(s,Val);//跳过该格不经过(这里可以不用加判断if(i != n || j != m),因为n-1,m一定会经过n,m) if(val[i][j+1] == INF || val[i+1][j] == INF)continue; s=s+(1<<bit[j-1])+2*(1<<bit[j]); if(!d)HashCalState(s,Val+val[i+1][j]+val[i][j+1]+val[i][j]);//注意这里一定还要加上val[i][j] else HashCalState(s,Val+val[i+1][j]+val[i][j]);//如果i,j+1已经由上面一行到达则不能重复累加该点价值 }else if(!p && q){ if(val[i][j+1] != INF){ //if(!d)Val=Val+val[i][j+1];//这里不能这样改变Val,因为会影响下一个if里面的Val if(!d)HashCalState(s,Val+val[i][j+1]); else HashCalState(s,Val);//如果i,j+1已经由上面一行到达则不能重复累加该点价值 } if(val[i+1][j] != INF){ s=s+q*(1<<bit[j-1])-q*(1<<bit[j]); Val=Val+val[i+1][j]; HashCalState(s,Val); } }else if(p && !q){ if(val[i+1][j] != INF)HashCalState(s,Val+val[i+1][j]); if(val[i][j+1] != INF){ s=s-p*(1<<bit[j-1])+p*(1<<bit[j]); if(!d)HashCalState(s,Val+val[i][j+1]); else HashCalState(s,Val);//如果i,j+1已经由上面一行到达则不能重复累加该点价值 } }else if(p == 1 && q == 1){ int b=1; for(int t=j+1;t<=m;++t){ int v=(s>>bit[t])%4; if(v == 1)++b; if(v == 2)--b; if(!b){ s=s+(1<<bit[t])-2*(1<<bit[t]); break; } } s=s-(1<<bit[j-1])-(1<<bit[j]); HashCalState(s,Val); }else if(p == 2 && q == 2){ int b=1; for(int t=j-2;t>=0;--t){ int v=(s>>bit[t])%4; if(v == 2)++b; if(v == 1)--b; if(!b){ s=s-(1<<bit[t])+2*(1<<bit[t]); break; } } s=s-2*(1<<bit[j-1])-2*(1<<bit[j]); HashCalState(s,Val); }else if(p == 2 && q == 1){ s=s-2*(1<<bit[j-1])-(1<<bit[j]); HashCalState(s,Val); } } } for(int k=1;k<=total[index];++k)state[index][k]<<=2; } sum=dp[index][1];//for(int k=1;k<=total[index];++k)sum=max(sum,dp[index][k]);//这里可以不用for,因为最后到达n,m->n+1,m状态只有一种 }int main(){ int num=0; for(int i=0;i<N;++i)bit[i]=i<<1; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<N;++i)for(int j=1;j<N;++j)val[i][j]=INF;//这里i<=N,j<=N会覆盖bit的内存地址,教训啊 for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j)scanf("%d",&val[i][j]); } val[n+1][m]=0;//在最后一个下面添加一个虚拟格子可以经过,则插头dp后的路线一定是以最后一格结尾 DP(); printf("Case %d: %lld\n",++num,sum); } return 0;}/*7 81 1 1 1 1 1 1 1-1 -1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1 -1 -1 1 1 -1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1*/
0 0
- hdu3377之简单路径求最值
- HDU3377
- HDU3377 Plan
- HDU3377 Plan 插头dp
- Photoshop文字之——路径文字简单教程
- makefile 各文件指定路径之简单模版
- 记数据结构简单课设之无向图的简单路径
- BFS(简单路径打印)
- Canvas简单直线路径
- 邻接矩阵存储简单路径
- 【JZOJ 5483】 简单路径
- 简单图论之最短路径(两种算法)
- iOS经典讲解之获取沙盒文件路径写入和读取简单对象
- 第十二周项目四---- 利用遍历思想求解图问题之简单路径
- 第十二周项目四----利用遍历思想求解图问题之输出简单路径
- iOS经典讲解之获取沙盒文件路径写入和读取简单对象
- 最短路径之Dijkstra算法(摘自算法基础)【一些简单的解释,没有代码】
- BFS之最简单的迷宫问题(并打印路径)
- VirtualBox的四种网络连接方式
- 经典的机器学习方面源代码库(非常全,数据挖掘,计算机视觉,模式识别,信息检索相关领域都适用的了)
- 二叉树上的各种操作
- SUSE Linux 报错:too many open files in system
- ICE运行时环境备忘三
- hdu3377之简单路径求最值
- 在modal view中使用UINavigationController
- [04.28更新]C++ 单向链表的实现
- 微信公众帐号开发教程第3篇-开发模式启用及接口配置
- Linux shell 学习笔记 之 find命令的使用
- 搭建android版本更新服务器使用android系统自带的DownloadManager下载文件
- Windows下安装cab文件
- poj2516 Minimum Cost
- 二八定律