ZOJ 3213
- /*
- ZOJ 3213
- 好吧,看过那种括号表示法后,就崩溃了,实在受不了。情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法。
- 最小表示法不难写:
- 1)首先,要承认路径上有格子不选的情况,于是,在00的情况下,可扩展,也可不选。
- 2)不能出现环,因而不能有L=U的情况出现。
- 3)以下是模版代码,类同是必然。但转而求路径数的时候,应当去掉不扩展的情况,同时,在IF(L|U)的情况下,亦不必考虑当前是否为最后一个格子,
- 只需按写的转移即可。
- 4)增加独立插头时,必须在总的独立插头数小于2的情况下进行。
- 注意:之所以不能出现两个插头,是因为,独立插头是单向的路径,不能进了又出。限制这个条件是非常有必要的。而在此处我本以为若限制了条件就得不出
- 最优解,而其实,因为存在不选的状态,限制了这个条件依然是可以有最优解的。
- */
- #include<stdio.h>
- #include<string.h>
- #include<algorithm>
- #include<iostream>
- using namespace std;
- const int MAXD=;
- const int HASH=;
- const int STATE=;
- int N,M;
- int maze[MAXD][MAXD];
- int code[MAXD];
- int ch[MAXD];
- int num;
- int ans;
- struct HASHMAP
- {
- int head[HASH],next[STATE],size;
- int state[STATE],dp[STATE];
- void init()
- {
- size=;
- memset(head,-,sizeof(head));
- }
- void push(int st,int ans)
- {
- int i,h=st%HASH;
- for(i=head[h];i!=-;i=next[i])
- if(state[i]==st)
- {
- if(dp[i]<ans)dp[i]=ans;
- return;
- }
- state[size]=st;
- dp[size]=ans;
- next[size]=head[h];
- head[h]=size++;
- }
- }hm[];
- void decode(int *code,int m,int st)
- {
- num=st&;//??????
- st>>=;
- for(int i=m;i>=;i--)
- {
- code[i]=st&;
- st>>=;
- }
- }
- int encode(int *code,int m)
- {
- int cnt=;
- memset(ch,-,sizeof(ch));
- ch[]=;
- int st=;
- for(int i=;i<=m;i++)
- {
- if(ch[code[i]]==-)ch[code[i]]=cnt++;
- code[i]=ch[code[i]];
- st<<=;
- st|=code[i];
- }
- st<<=;
- st|=num;
- return st;
- }
- void shift(int *code,int m)
- {
- for(int i=m;i>;i--)code[i]=code[i-];
- code[]=;
- }
- void dpblank(int i,int j,int cur)
- {
- int k,left,up;
- for(k=;k<hm[cur].size;k++)
- {
- decode(code,M,hm[cur].state[k]);
- left=code[j-];
- up=code[j];
- if(left&&up)
- {
- if(left!=up)
- {
- code[j-]=code[j]=;
- for(int t=;t<=M;t++)
- if(code[t]==up)
- code[t]=left;
- if(j==M)shift(code,M);
- hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
- }
- }
- else if(left||up)
- {
- int t;
- if(left)t=left;
- else t=up;
- if(maze[i][j+])
- {
- code[j-]=;
- code[j]=t;
- hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
- }
- if(maze[i+][j])
- {
- code[j-]=t;
- code[j]=;
- hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
- }
- if(num<) //封住一端,增加一个独立插头。
- {
- num++;
- code[j-]=code[j]=;
- hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
- }
- }
- else
- {
- code[j-]=code[j]=; //讨论简单路径,只需不讨论不选的情况就可以了。
- hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]);
- if(maze[i][j+]&&maze[i+][j])
- {
- code[j-]=code[j]=;
- hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
- }
- if(num<)
- {
- num++;
- if(maze[i][j+])
- {
- code[j]=;
- code[j-]=;
- hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
- }
- if(maze[i+][j])
- {
- code[j-]=;
- code[j]=;
- hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
- }
- }
- }
- }
- }
- void dpblock(int i,int j,int cur)
- {
- int k;
- for(k=;k<hm[cur].size;k++)
- {
- decode(code,M,hm[cur].state[k]);//?????!!!
- code[j-]=code[j]=;
- if(j==M)shift(code,M);
- hm[cur^].push(encode(code,M),hm[cur].dp[k]);
- }
- }
- void init()
- {
- scanf("%d%d",&N,&M);
- ans=;
- memset(maze,,sizeof(maze));//???????
- for(int i=;i<=N;i++)
- for(int j=;j<=M;j++)
- {
- scanf("%d",&maze[i][j]);
- if(maze[i][j]>ans)ans=maze[i][j];
- }
- }
- void solve()
- {
- int i,j,cur=;
- hm[cur].init();
- hm[cur].push(,);
- for(i=;i<=N;i++)
- for(int j=;j<=M;j++)
- {
- hm[cur^].init();
- if(maze[i][j])dpblank(i,j,cur);
- else dpblock(i,j,cur);
- cur^=;
- }
- for(i=;i<hm[cur].size;i++)
- if(hm[cur].dp[i]>ans)
- ans=hm[cur].dp[i];
- printf("%d\n",ans);
- }
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- init();
- solve();
- }
- return ;
- }
更新代码,自写的。WA了N久,感觉有几个问题要注意一下:
应当初始化图为0;
记住在增加独立插头时,任何时候要考虑是否<2
- #include <iostream>
- #include <stdio.h>
- #include <cstring>
- using namespace std;
- const int MAXD=;
- const int MAXL=;
- const int MAXH=;
- int n,m;
- int ans; int num;
- int map[MAXD][MAXD];
- int code[MAXD]; int pos[MAXD],stac[MAXD];
- int tmp[MAXD];
- struct HASHMAP{
- int hash[MAXL],state[MAXH],next[MAXH];
- int f[MAXH];
- int size;
- void init(){
- size=;
- memset(hash,-,sizeof(hash));
- }
- void push(int st,int anst) {
- int h=st%MAXL;
- for(int i=hash[h];i!=-;i=next[i]){
- if(state[i]==st){
- if(f[i]<anst){
- f[i]=anst;
- }
- return ;
- }
- }
- state[size]=st;
- f[size]=anst;
- next[size]=hash[h];
- hash[h]=size++;
- }
- }hm[];
- void decode(int st){
- for(int i=m;i>=;i--){
- int t=st&;
- code[i]=t;
- st=st>>;
- }
- }
- int fd_r(int j){
- int top=-;
- for(int i=;i<=m;i++){
- if(code[i]==) continue;
- else if(code[i]==){
- ++top;
- pos[top]=i; stac[top]=code[i];
- }
- else if(code[i]==){
- if(pos[top]==j) return i;
- else top--;
- }
- }
- }
- int fd_l(int j){
- int top=-;
- for(int i=;i<=m;i++){
- if(code[i]==) continue;
- else if(code[i]==){
- ++top;
- pos[top]=i; stac[top]=code[i];
- }
- else if(code[i]==){
- if(i==j) return pos[top];
- else top--;
- }
- }
- }
- void dpblank(int i,int j,int cur){
- int em;int tmpst; int ls,us,tts;
- for(int e=;e<hm[cur].size;e++){
- int st=hm[cur].state[e];
- num=st&;
- st>>=;
- decode(st);
- int left=code[j-],up=code[j];
- ls=(m-j+)*; us=(m-j)*;
- if(!left&&!up){
- tmpst=(st^(left<<ls))^(up<<us);
- if(j==m) tmpst=tmpst>>;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]);
- if(map[i+][j]>&&map[i][j+]>){
- tmpst=(st^(left<<ls))^(<<ls);
- tmpst=(tmpst^(up<<us))^(<<us);
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- if(num<){
- num++;
- if(map[i][j+]>){
- tmpst=(st^(left<<ls));
- tmpst=(tmpst^(up<<us))^(<<us);
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- if(map[i+][j]>){
- tmpst=(st^(left<<ls))^(<<ls);
- tmpst=(tmpst^(up<<us));
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- }
- }
- else if(left&&up){
- if(left==&&up==){
- int tt=fd_r(j);
- tts=(m-tt)*;
- tmpst=(st^(code[tt]<<tts))^(<<tts);
- tmpst=(tmpst^(left<<ls));
- tmpst=(tmpst^(up<<us));
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- else if(left==&&up==){
- int tt=fd_l(j-);
- tts=(m-tt)*;
- tmpst=(st^(code[tt]<<tts))^(<<tts);
- tmpst=(tmpst^(left<<ls));
- tmpst=(tmpst^(up<<us));
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- else if(left==&&up==){
- tmpst=(st^(left<<ls));
- tmpst=(tmpst^(up<<us));
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- else if(left==&&up==){
- tmpst=(st^(left<<ls));
- tmpst=(tmpst^(up<<us));
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- else if(left==&&up!=){
- int tt;
- if(up==) tt=fd_r(j);
- else tt=fd_l(j);
- tts=(m-tt)*;
- tmpst=st^(left<<ls);
- tmpst=tmpst^(up<<us);
- tmpst=(tmpst^(code[tt]<<tts))^(<<tts);
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- else if(left!=&&up==){
- int tt;
- if(left==) tt=fd_r(j-);
- else tt=fd_l(j-);
- tts=(m-tt)*;
- tmpst=st^(left<<ls);
- tmpst=tmpst^(up<<us);
- tmpst=(tmpst^(code[tt]<<tts))^(<<tts);
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- }
- else{
- int tt,cott;
- if(left) tt=left;
- else tt=up;
- if(map[i][j+]>){
- tmpst=st^(up<<us)^(tt<<us);
- tmpst=tmpst^(left<<ls);
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- if(map[i+][j]>){
- tmpst=st^(left<<ls)^(tt<<ls);
- tmpst=tmpst^(up<<us);
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- if(tt==&&num<){ //忘了限制条件<2,WA了N久。
- tmpst=st^(left<<ls)^(up<<us);
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=(num+);
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- if(left!=&&up!=&&num<){
- int sp=(tt==left? j-: j);
- tts=(m-sp)*;
- if(tt==) cott=fd_r(sp);
- else cott=fd_l(sp);
- tmpst=st^(code[sp]<<tts)^(code[cott]<<((m-cott)*))^(<<((m-cott)*));
- if(j==m) tmpst>>=;
- num++;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
- }
- }
- }
- }
- void dpblock(int i,int j,int cur){
- int em; int tmpst;
- for(int k=;k<hm[cur].size;k++){
- int st=hm[cur].state[k];
- num=st&;
- st>>=;
- decode(st);
- tmpst=st^(code[j]<<((m-j)*))^(code[j-]<<((m-j+)*));
- if(j==m) tmpst>>=;
- tmpst<<=;
- tmpst|=num;
- hm[cur^].push(tmpst,hm[cur].f[k]);
- }
- }
- void solve(){
- int cur=,i;
- hm[cur].init();
- hm[cur].push(,);
- for( i=;i<=n;i++){
- for(int j=;j<=m;j++){
- hm[cur^].init();
- if(map[i][j]>) dpblank(i,j,cur);
- else dpblock(i,j,cur);
- cur=cur^;
- }
- }
- for( i=;i<hm[cur].size;i++)
- if(hm[cur].f[i]>ans) ans=hm[cur].f[i];
- printf("%d\n",ans);
- }
- int main(){
- int T; int i,j;
- scanf("%d",&T);
- while(T--){
- ans=;
- scanf("%d%d",&n,&m);
- memset(map,,sizeof(map));
- for(i=;i<=n;i++){
- for(j=;j<=m;j++){
- scanf("%d",&map[i][j]);
- if(map[i][j]>ans) ans=map[i][j];
- }
- }
- solve();
- }
- return ;
- }
ZOJ 3213的更多相关文章
- ZOJ 3213 Beautiful Meadow 简单路径 插头DP
简单路径的题目,其实就是在状态后面多记了有多少个独立插头. 分类讨论独立插头: 1.只存在上插头或者左插头,可以选择作为独立插头. 2.都不存在上插头和左插头,选择作为独立插头的同时要标号为新的连通块 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- 插头dp的几个模板
/* ural1519 求经过全部可行点的哈密顿回路的个数 括号匹配法,转移有点复杂,可是时间空间比較小 */ #include<cstdio> #include<cstring&g ...
- ZOJ People Counting
第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ 3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...
- ZOJ 3686 A Simple Tree Problem
A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a rooted tree, each no ...
- ZOJ Problem Set - 1394 Polar Explorer
这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...
- ZOJ Problem Set - 1392 The Hardest Problem Ever
放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...
- ZOJ Problem Set - 1049 I Think I Need a Houseboat
这道题目说白了是一道平面几何的数学问题,重在理解题目的意思: 题目说,弗雷德想买地盖房养老,但是土地每年会被密西西比河淹掉一部分,而且经调查是以半圆形的方式淹没的,每年淹没50平方英里,以初始水岸线为 ...
- ZOJ Problem Set - 1006 Do the Untwist
今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...
随机推荐
- 开启和安装Kubernetes 基于Docker For Windows
0.最近发现,Docker For Windows Stable在Enable Kubernetes这个问题上是有Bug的,建议切换到Edge版本,并且采用下文AliyunContainerServi ...
- 微信小程序图片选择,预览和删除
这里均用的是小程序原生api 废话不多说直接上栗子: <view class="addImv"> <!--这个是已经选好的图片--> <view wx ...
- QT 制作串口调试小助手----(小白篇)
一.成品图展示 简介:因zigbee实验,制作一个相对简易版的上位机,接收来自zigbee无线传感采集的温湿度.光照等数据. 并且将数据部分描绘成实时动态折线统计图. 二.主要功能介绍 主要使用QT自 ...
- 微信小程序调用微信支付
1,首先我们先缕清支付的整个流程,详见https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3,第一 ...
- 实例化flask的参数及对app的配置
Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? 首先展示一下: from ...
- [laravel]用户异地登录后踢掉之前的登录
不同用户和服务器之间由一个唯一的session来区分,但是一般情况下不同的session对应的用户model可以是同一个. 为了实现只能同时在一个地方登陆,可以在用户的字段里增加一个last_sess ...
- SAS学习笔记之《SAS编程与数据挖掘商业案例》(5)SAS宏语言、SQL过程
SAS学习笔记之<SAS编程与数据挖掘商业案例>(5)SAS宏语言.SQL过程 1. 一个SAS程序可能包含一个或几个语言成分: DATA步或PROC步 全程语句 SAS组件语言(SCL) ...
- Android文件操作报open failed: EBUSY (Device or resource busy)
Android删除文件后重新创建时偶尔出现 open failed: EBUSY (Device or resource busy)错误,该错误是Android系统的一个bug,大概的意思类似于win ...
- Git的使用及托管代码到GitHub
首先Git是一个开源的分布式版本控制工具,用git创建代码仓库. 仓库(Repository)是用于保存版本管理所需信息的地方,本地代码 提交到 代码仓库中,如果需要还可以 再推送到 远程仓库中. 所 ...
- sql server 大数据跨服务器迁移表数据——使用链接服务器
1.创建链接服务器(填写链接服务器.远程登录.使用密码) 2.188.188.1.177是远程的 select count(*) from [188.188.1.177].BigDataAnalysi ...