[caioj]1493: 基于连通性状态压缩的动态规划问题:Plan
来源:互联网 发布:圣山 知乎 编辑:程序博客网 时间:2024/06/15 03:20
题目描述
【题目描述】
给你一个 n * m 的矩阵,矩阵中的每个格子都有一个分数,求从左上角走到右下角的最大分数,每个格子只能经过一次,也可以不经过。
如图,一个 3*3 的矩阵,最大分数为61 。
【输入】
多组数据,每组数据的第一行有两个整数 n 和 m(1<= n <=8,1<= m <=9) ,下面给出一个 n * m 的矩阵,矩阵中每个分数的值在 -2000 到 2000之间。
【输出】
对于第 i 组数据,输出 Case i: ans ,ans 为最大分数。
【样例输入】
2 2
1 2
3 1
3 3
0 -20 100
1 -20 -20
1 1 1
【样例输出】
Case 1: 5
Case 2: 61
其实和裸题也差不多。。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define LL long longconst int mod=100037;int n,m,map[15][15],now=0,list[2][mod],num[2];// 状态列表 状态总数 LL state[2][mod],ans,val[15][15];int HASH[mod];//每种状态的数目LL get(int s,int p)//获取状态s从右向左数的第p位 {return (s>>((p-1)*2))&3;}void change(int &s,int p,int v)//把状态s的第p位改成v { s^=get(s,p)<<((p-1)*2); s^=(v)<<((p-1)*2);}void update(LL &x,LL y){x=max(x,y);}void add(int now,int st,LL sum){ int ss=st%mod; while(HASH[ss]!=-1&&list[now][HASH[ss]]!=st) { ss++;ss%=mod; if(ss==0)ss=1; } if(HASH[ss]==-1) { HASH[ss]=++num[now]; list[now][num[now]]=st; state[now][num[now]]=sum; } else update(state[now][HASH[ss]],sum);}void work(){ state[0][1]=val[1][1];num[0]=1;list[0][1]=1; //一开始的状态必须设成这样,确保起点为(1,1) for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { now^=1; num[now]=0; memset(HASH,-1,sizeof(HASH)); for(int k=1;k<=num[now^1];k++) { int st=list[now^1][k]; LL sum=state[now^1][k]; int p=get(st,j); int q=get(st,j+1); int d=get(st,j+2);//为了避免重复计算某个格子价值,引入d这个括号 if(!p&&!q) { add(now,st,sum);//因为不一定经过所有格子,所以有这种状态 if(map[i][j+1]&&map[i+1][j]) { change(st,j,1); change(st,j+1,2); if(!d)add(now,st,sum+val[i][j]+val[i][j+1]+val[i+1][j]); else add(now,st,sum+val[i][j]+val[i+1][j]); //上面两个一定要加上val[i][j]啊!因为它的价值没有被累加过! } } else if(!p&&q) { if(i==n&&j==m) { update(ans,sum); continue; } if(map[i][j+1])//从上面到达(n,m) { if(!d)add(now,st,sum+val[i][j+1]); else add(now,st,sum); } if(map[i+1][j]) { change(st,j,q); change(st,j+1,0); add(now,st,sum+val[i+1][j]); } } else if(p&&!q) { if(i==n&&j==m)//从左面到达(n,m) { update(ans,sum); continue; } if(map[i+1][j])add(now,st,sum+val[i+1][j]); if(map[i][j+1]) { change(st,j,0); change(st,j+1,p); if(!d)add(now,st,sum+val[i][j+1]); else add(now,st,sum); } } else if(p==2&&q==1) { change(st,j,0); change(st,j+1,0); add(now,st,sum); } else if(p==1&&q==1) { int top=1; for(int pos=j+2;pos<=m+1;pos++) { int temp=get(st,pos); if(temp==1)top++; if(temp==2)top--; if(top==0) { change(st,j,0); change(st,j+1,0); change(st,pos,1); add(now,st,sum); break; } } } else if(p==2&&q==2) { int top=1; for(int pos=j-1;pos;pos--) { int temp=get(st,pos); if(temp==2)top++; if(temp==1)top--; if(top==0) { change(st,j,0); change(st,j+1,0); change(st,pos,2); add(now,st,sum); break; } } } } } for(int j=1;j<=num[now];j++)list[now][j]<<=2; }}int main(){ int Case=0; while(scanf("%d%d",&n,&m)!=EOF) { ans=-(1LL<<31);now=0; memset(map,0,sizeof(map)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%lld",&val[i][j]); map[i][j]=1; } work(); printf("Case %d: %lld\n",++Case,ans); }}
阅读全文
0 0
- [caioj]1493: 基于连通性状态压缩的动态规划问题:Plan
- [caioj]1493: 基于连通性状态压缩的动态规划问题:Plan
- [caioj]1489: 基于连通性状态压缩的动态规划问题:Formula 1
- [caioj]1490: 基于连通性状态压缩的动态规划问题:Eat the Trees
- [caioj]1491: 基于连通性状态压缩的动态规划问题:Tony's Tour
- [caioj]1492: 基于连通性状态压缩的动态规划问题:Pipes
- 【caioj】1489: 基于连通性状态压缩的动态规划问题:Formula 1 Ural1519
- [caioj]1491: 基于连通性状态压缩的动态规划问题:Tony's Tour
- 基于连通性状态压缩的动态规划问题
- 动态规划专题:算法合集之《基于连通性状态压缩动态规划问题》
- 男人8题之Tony's TourPKU1739基于连通性状态压缩的动态规划
- 基于连通性状态压缩的动态规划--【插头DP】模板超级详细解释
- Ural 1519 Formula 1 基于连通性的状态压缩动态规划
- POJ1739 基于连通性的状态压缩dp
- 基于连通性的状态压缩DP
- 【基于联通性的状态压缩动态规划】
- 状态压缩的动态规划
- 【基于连通性的状态压缩DP】【NOI2007】生成树计数
- Android下载OKHTTP
- CRC8 校验
- 获取计算机名和局域网内的工作组名称
- Linux系统日期时间设定方法及与Internet时间同步的设置
- MIME类型
- [caioj]1493: 基于连通性状态压缩的动态规划问题:Plan
- Android Service 初探(一)
- SQL语句编写规范
- ThankPHP5中支付宝实现
- InputStreamReader 和 OutputStreamWriter用法简介
- ERROR 1142 CREATE command denied to user 'root'@'xxxxx
- 怎样合并字典最符合 Python 语言习惯?
- hdu1166.敌兵布阵
- Chrome 浏览器调试CSS