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?
 
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
 
Output
Output Format is "Case ID: ANS" one line for each data

Don't print any empty line to the output
 
Sample Input
2 2
1 2
3 1
3 3
0 -20 100
1 -20 -20
1 1 1
 
Sample Output
Case 1: 5
Case 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 0
0 # # # 0
------
1 0 1 |# 0
1 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 99999999
typedef 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 8
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 1
*/

hdu3377之简单路径求最值的更多相关文章

  1. 洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小

    P4149 [IOI2011]Race 题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK,且边的数量最小. 输入格式 第一行包含两个整数 n, Kn,K. 接下来 n - 1n−1 行 ...

  2. _DataStructure_C_Impl:求图G中从顶点u到顶点v的一条简单路径

    #pragma once #include<stdio.h> #include<stdlib.h> #define StackSize 100 typedef int Data ...

  3. 【Leetcode】二叉树简单路径最大和问题

    问题一:二叉树任意两个叶子间简单路径最大和 示例: -100 /   \ 2   100 /  \ 10   20 思路:这个问题适用于递归思路. 首先,将问题简单化:假设包含最大和summax的简单 ...

  4. Sql示例说明如何分组后求中间值--【叶子】

    原文:Sql示例说明如何分组后求中间值--[叶子] 这里所谓的分组后求中间值是个什么概念呢? 我举个例子来说明一下: 假设我们现在有下面这样一个表: type        name price -- ...

  5. POJ 1797 Heavy Transportation(Dijkstra变形——最长路径最小权值)

    题目链接: http://poj.org/problem?id=1797 Background Hugo Heavy is happy. After the breakdown of the Carg ...

  6. [简单路径] Useful Decomposition

    Ramesses knows a lot about problems involving trees (undirected connected graphs without cycles)! He ...

  7. ACM3 求最值

    /*2*2014.11.18*求最值*描述:给定N个整数(1<=N<=100),求出这N个数中的最大值,最小值.*输入:多组数据,第一行为一个整数N,第二行为N个不超过100的正整数,用空 ...

  8. [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...

  9. hdu4521-小明系列问题——小明序列(线段树区间求最值)

    题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为  线段树解法. #include ...

随机推荐

  1. (JavaScript基础向)日常小发现:forEach等函数的第二个参数的用法

    forEach函数用得平时用得比较多,但是从来没想到forEach函数还有第二个参数. 这里是菜鸟教程对forEach函数的详细说明:forEach的详细说明. 如上图,forEach函数有第二个参数 ...

  2. fc---输出历史命令列表

    fc指令 fc指令可以用于输出历史命令列表,也可以通过调用vi编辑器对历史指令内容进行编辑输出. 语法: fc [-e ename] [-lnr] [first] [last] 选项: -l:显示历史 ...

  3. PHP截取字符串长度

    <?php function str_cut($string, $start=0,$length, $dot = '..') {    $strlen = strlen($string);    ...

  4. 阅读笔记—MVC

    MVC设计模式 Model 1 体系结构 在Model 1 体系结构中,每一个请求的目标都是JSP页面.JSP页面负责完成请求所需要的而所有任务,其中包括验证客户.使用JavaBeans访问数据库及管 ...

  5. 网站新建移动站,做了link rel="canonical" 等于主站URL后,全站被百度K了。

    移动站所有页面的权重都指向主站的首页,估计就是被K的原因.毕竟那么多网页一下权重那么多,当然被K了.不知道啥时候能好.

  6. BZOJ3192: [JLOI2013]删除物品(splay)

    Description   箱子再分配问题需要解决如下问题:  (1)一共有N个物品,堆成M堆.  (2)所有物品都是一样的,但是它们有不同的优先级.  (3)你只能够移动某堆中位于顶端的物品.  ( ...

  7. 字符设备驱动-------Linux异常处理体系结构

    裸机中断流程 外部触发 CPU 发生中断, 强制的跳到异常向量处 跳转到具体函数 保存被中断处的现场(各种寄存器的值) 执行中断处理函数,处理具体任务 恢复被中断的现场 Linux处理异常流程 异常发 ...

  8. 【习题 7-10 Uva11214】Guarding the Chessboard

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 可以想见最后深度不会很深吧.. 然后皇后之间互相攻击到是允许的.. 就这样 [代码] /* 1.Shoud it u ...

  9. 第6章4节《MonkeyRunner源代码剖析》Monkey原理分析-事件源-事件源概览-翻译命令字串

    在第2节中我们看到了MonkeySourceNetwork是怎样从Socket中获取MonkeyRunner发送过来的命令字串的,可是最后怎样将它翻译成事件的代码我们还没有进行分析,由于在那之前我们还 ...

  10. 使用solr的DIHandler 构建mysql大表全量索引,内存溢出问题的解决方法

    solr官方给出的解决方式是: DataImportHandler is designed to stream row one-by-one. It passes a fetch size value ...