hdu3377之简单路径求最值
Plan
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 686 Accepted Submission(s): 234
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?
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
Don't print any empty line to the output
2 2
1 2
3 1
3 3
0 -20 100
1 -20 -20
1 1 1
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之简单路径求最值的更多相关文章
- 洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小
P4149 [IOI2011]Race 题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK,且边的数量最小. 输入格式 第一行包含两个整数 n, Kn,K. 接下来 n - 1n−1 行 ...
- _DataStructure_C_Impl:求图G中从顶点u到顶点v的一条简单路径
#pragma once #include<stdio.h> #include<stdlib.h> #define StackSize 100 typedef int Data ...
- 【Leetcode】二叉树简单路径最大和问题
问题一:二叉树任意两个叶子间简单路径最大和 示例: -100 / \ 2 100 / \ 10 20 思路:这个问题适用于递归思路. 首先,将问题简单化:假设包含最大和summax的简单 ...
- Sql示例说明如何分组后求中间值--【叶子】
原文:Sql示例说明如何分组后求中间值--[叶子] 这里所谓的分组后求中间值是个什么概念呢? 我举个例子来说明一下: 假设我们现在有下面这样一个表: type name price -- ...
- POJ 1797 Heavy Transportation(Dijkstra变形——最长路径最小权值)
题目链接: http://poj.org/problem?id=1797 Background Hugo Heavy is happy. After the breakdown of the Carg ...
- [简单路径] Useful Decomposition
Ramesses knows a lot about problems involving trees (undirected connected graphs without cycles)! He ...
- ACM3 求最值
/*2*2014.11.18*求最值*描述:给定N个整数(1<=N<=100),求出这N个数中的最大值,最小值.*输入:多组数据,第一行为一个整数N,第二行为N个不超过100的正整数,用空 ...
- [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...
- hdu4521-小明系列问题——小明序列(线段树区间求最值)
题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为 线段树解法. #include ...
随机推荐
- nodejs学习(三)--express连接mysql数据库,mysql查询封装
一.说一下 连接不同的数据库需要安装相应的插件,此demo使用mysql数据库,需自行安装mysql数据库软件. 新建数据库webapp, 新建表users: 二.直接开码 npm install m ...
- 商业模式(二):P2P网贷平台,利差和服务费为主的金融玩法
2014~2015,先后在2家P2P平台工作过,还了解过其它若干武汉P2P平台. 结合自己的工作经历和理财经历,说几句~ 1.P2P网贷这种金融类的创业项目和经营风险,远高于制造业和服务业~ ...
- Prism 框架基础架构
概要 Prism提供指导,帮助您更轻松地设计和构建,灵活且易于维护的客户端业务应用程序,这些应用程序可在Windows运行时,Windows Presentation Foundation(WPF)桌 ...
- BZOJ 1108 POI2007 天然气管道Gaz
题目大意:给定平面上的n个黑点和n个白点.一个黑点仅仅能和右下方的白点匹配.代价为曼哈顿距离,求最小权值完备匹配 STO OTZ STO OTZ STO OTZ ans=Σ(y黑-y白+x白-x黑) ...
- Android启动原理剖析
我们知道Android是以一个Activity为单位的,可是我们并没有看到一个Activity是怎么開始启动的. 今天我 们就从Android的源码開始讲吧. ActivityThread: Andr ...
- Android中关于JNI 的学习(零)简单的样例,简单地入门
Android中JNI的作用,就是让Java可以去调用由C/C++实现的代码,为了实现这个功能.须要用到Anrdoid提供的NDK工具包,在这里不讲怎样配置了,好麻烦,配置了好久. . . 本质上,J ...
- Flume的可靠性
Flume的可靠性 当节点出现故障时,日志能够被传送到其他节点上而不会丢失. Flume提供了三种级别的可靠性保障,从强到弱依次分别为:end-to- end(收到数据agent首先将event写到磁 ...
- 洛谷P3954 成绩【民间数据】
题目背景 数据已修复 题目描述 牛牛最近学习了C++入门课程,这门课程的总成绩计算方法是: 总成绩=作业成绩×20%+小测成绩×30%+期末考试成绩×50% 牛牛想知道,这门课程自己最终能得到多少分. ...
- golang sync.WaitGroup
//阻塞,直到WaitGroup中的所以过程完成. import ( "fmt" "sync" ) func wgProcess(wg *sync.WaitGr ...
- [USACO08JAN]电话线Telephone Lines(分层图)/洛谷P1948
这道题其实是分层图,但和裸的分层图不太一样.因为它只要求路径总权值为路径上最大一条路径的权值,但仔细考虑,这同时也满足一个贪心的性质,那就是当你每次用路径总权值小的方案来更新,那么可以保证新的路径权值 ...