f(i,j,S)表示到(i,j),且经由的路径上的颜色集合为S的价值的最小值,从上方和左方转移过来即可。

要注意,内存不足,需要滚动数组优化,即使用了map,还是需要。

路径输出的时候,可以再跑一遍dp,这样就不用再开一个大数组了。

我的写法比较菜。卡了常数

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int w[401][401],c[401][401];
typedef pair<int,int> Point;
map<int,int>f[401][401];
typedef pair<int,Point> data;
typedef map<int,int>::iterator ITER;
map<int,data>g[401][401];
int n,K,W;
int calc(int x)
{
int res=0;
while(x)
{
res+=(x&1);
x>>=1;
}
return res;
}
Point path[1001];
int e;
int main()
{
scanf("%d%d%d",&n,&K,&W);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&w[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&c[i][j]);
if(w[1][1]>W)
{
puts("-1");
return 0;
}
f[1][1][1<<(c[1][1]-1)]=w[1][1];
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)
{
if(i>1 && j>1)
{
for(ITER it=f[i-1][j].begin();it!=f[i-1][j].end();++it)
{
int nS=(*it).first|(1<<(c[i][j]-1)),tmp=(*it).second+w[i][j];
if(f[i][j].find(nS)==f[i][j].end())
{
if(tmp<=W)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i-1,j));
}
}
else if(f[i][j][nS]>tmp)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i-1,j));
}
}
for(ITER it=f[i][j-1].begin();it!=f[i][j-1].end();++it)
{
int nS=(*it).first|(1<<(c[i][j]-1)),tmp=(*it).second+w[i][j];
if(f[i][j].find(nS)==f[i][j].end())
{
if(tmp<=W)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i,j-1));
}
}
else if(f[i][j][nS]>tmp)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i,j-1));
}
}
}
else if(i==1 && j>1)
{
for(ITER it=f[i][j-1].begin();it!=f[i][j-1].end();++it)
{
int nS=(*it).first|(1<<(c[i][j]-1)),tmp=(*it).second+w[i][j];
if(f[i][j].find(nS)==f[i][j].end())
{
if(tmp<=W)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i,j-1));
}
}
else if(f[i][j][nS]>tmp)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i,j-1));
}
}
}
else if(i>1 && j==1)
{
for(ITER it=f[i-1][j].begin();it!=f[i-1][j].end();++it)
{
int nS=(*it).first|(1<<(c[i][j]-1)),tmp=(*it).second+w[i][j];
if(f[i][j].find(nS)==f[i][j].end())
{
if(tmp<=W)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i-1,j));
}
}
else if(f[i][j][nS]>tmp)
{
f[i][j][nS]=tmp;
g[i][j][nS]=data((*it).first,Point(i-1,j));
}
}
}
}
if(i>=3)
{
for(int j=1;j<=n;++j)
{
f[i-2][j].clear();
// g[i-2][j].
}
}
}
int ans=2147483647;
int anS;
for(ITER it=f[n][n].begin();it!=f[n][n].end();++it)
{
int tmp=calc((*it).first);
if(tmp<ans)
{
ans=tmp;
anS=(*it).first;
}
}
if(ans==2147483647)
puts("-1");
else
{
printf("%d\n",ans);
data U=data(anS,Point(n,n));
path[++e]=Point(n,n);
while(U.second!=Point(1,1))
{
U=g[U.second.first][U.second.second][U.first];
path[++e]=U.second;
}
for(int i=e;i>=1;--i)
printf("%d %d%c",path[i].first,path[i].second,i==1 ? '\n' : ' ');
}
return 0;
}

【滚动数组】【状压dp】Gym - 100956F - Colored Path的更多相关文章

  1. 状压dp Gym - 100676G

    http://codeforces.com/gym/100676 题目大意: 给你n个科目,m个关系,例如A->B,表示要学习B科目,一定要把A科目学习掉.同理,如果还有C->B,那么,B ...

  2. zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)

    Time Limit: 10 Seconds      Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...

  3. Codeforces Gym 100015F Fighting for Triangles 状压DP

    Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...

  4. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  5. POJ 3311 Hie with the Pie (状压DP)

    dp[i][j][k] i代表此层用的状态序号 j上一层用的状态序号 k是层数&1(滚动数组) 标准流程 先预处理出所有合法数据存在status里 然后独立处理第一层 然后根据前一层的max推 ...

  6. ZOJ3802 Easy 2048 Again (状压DP)

    ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?proble ...

  7. 状压DP uvalive 6560

    // 状压DP uvalive 6560 // 题意:相邻格子之间可以合并,合并后的格子的值是之前两个格子的乘积,没有合并的为0,求最大价值 // 思路: // dp[i][j]:第i行j状态下的值 ...

  8. ZOJ 3723 (浙大月赛)状压DP

    A了一整天~~~终于搞掉了. 真是血都A出来了. 题目意思很清楚,肯定是状压DP. 我们可以联系一下POJ 1185  炮兵阵地,经典的状压DP. 两道题的区别就在于,这道题的攻击是可以被X挡住的,而 ...

  9. hdu_4529_郑厂长系列故事——N骑士问题(状压DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4529 题意:中文,不解释 题解:状压DP,dp[i][j][k][s]表示第i行当前用了j个骑士,i- ...

随机推荐

  1. android 5.0新特性学习--视图阴影

    android 5.0的视图阴影主要是体验出层次性,就是在一个物体上面叠加上一层的设计,而这种设计就是除了传统的,x,y的纸面层,还有就是透过纸面的z轴的层次设计. elevation: 高度,静态属 ...

  2. ecshop后台增加模块菜单项详细教程(图文)

    有的时候我们会在后台增加新的功能,菜单项是一个程序的入口,是必不可少的,如何在后台增加菜单项呢,大家可以参考下面的教程:   例如:想在后台左侧的菜单栏的"促销管理"下添加一个&q ...

  3. 微信小程序Server端环境配置

    主要内容:1. SSL免费证书申请步骤2. Nginx HTTPS 配置3. TLS 1.2 升级过程 微信小程序要求使用 https 发送请求,那么Web服务器就要配置成支持 https,需要先申请 ...

  4. android脚步---跟随手指动的小球

    这次的学习主要是在包里面除自动生成的mainactivity.java之外,再新建一个class, DrawView,在mainactivity里面调用DrawView. 在DrawView里面主要是 ...

  5. Activity与Service之间交互并播放歌曲的实现代码

    Activity与Service之间交互并播放歌曲,为了方便,我把要播放的歌曲定死了,大家可以灵活改进 MService: 复制代码代码如下: package com.tiantian.test;im ...

  6. (poj 3660) Cow Contest (floyd算法+传递闭包)

    题目链接:http://poj.org/problem?id=3660 Description N ( ≤ N ≤ ) cows, conveniently numbered ..N, are par ...

  7. 转html5语义化标签总结一

    HTML 5的革新之一:语义化标签一节元素标签. 在HTML 5出来之前,我们用div来表示页面章节,但是这些div都没有实际意义.(即使我们用css样式的id和class形容这块内容的意义).这些标 ...

  8. Android IBinder的linkToDeath介绍

    先看官方解释: The linkToDeath() method can be used to register a IBinder.DeathRecipient with the IBinder, ...

  9. 一道题看懂OC的文件管理:NSFileManager,计算文件包含内存大小

    计算文件夹下所有文件的大小 // 查看错误信息 __autoreleasing NSError *error; // 文件管理对象 NSFileManager *manager = [NSFileMa ...

  10. RS485中继器电路(转)

    源:RS485中继器电路(转) --------以上部分请勿修改!------------- RS-485中继器 由于在双绞线上的电平损耗,RS-485标准通信的最大传输距离是1200米(4000英尺 ...