状态压缩动态规划感觉都不是那么好写,看网上的人说这题是2011年ACM/ICPC中的水题,暗地里感觉很是惭愧啊(花了将近4个小时),结果还算是勉勉强强地弄出来了。
与往常一样,先说说题目的意思和思路,再给出代码,最后分享出代码比较精髓的地方(有的话),另这随笔主要目的是方便自己以后使用,当然很是欢迎大家指出错误和批评。那就开始了:
题目说的是有一群小伙伴去旅游,某个人对某以特定的城市有一定的兴趣,并且多人一同去还有奖励,当然门票还是要的嘛。
输入:N(小伙伴的个数),M(城市的个数)紧接着的一行是各个城市的门票价格,然后是一个N*M的矩阵表示第i名游客对j城市的感兴趣度,最后还有一个N*N的矩阵表示若i旅客与j旅客结伴出行的话可以得到的奖金。特别注意的是游客可以中间插入,也可以中途离开,但若是中途离开以后就不得在后面的观光中出现.
输出:最后的结果若<=0,那么就输出"STAY HOME"。
思路还是状态压缩嘛,具体来讲就是用一个叫DP[i]的数组记录从开始的城市到当前城市中总共值中选出最大的,在用一个temp[i]数组来保存相应的DP[i]值,为后面的DP做准备,然后交替进行,期间必须保证离队以后的人不可以再次入队,这点怎么保证呢?
for(int i=1;i<=M;i++)
{
for(int j=0;j<bit;j++) dp[j]=MIN;
for(int j=0;j<bit;j++)
{
int weight=calculate(j,i);
for(int k=j;k<bit;k=(k+1)|j)
{
dp[j]=max(dp[j],temp[k]+weight);
}
}
for(int j=0;j<bit;j++) temp[j]=dp[j];
}
就用这几行代码就可以搞定了。第一个for循环是从1到M的城市,第二行是对于城市i的状态为j,第三行是总结出从1到i可以达到的最大值,中间的temp一直记录这些最大值,这与滚动数组非常类似。为什么这样写就能保证中途掉队的的在以后就一定加不进来呢?那么你可以仔细看看第三个for循环k是如何增加的(k=(k+1)|j)保证了变化后的k中一定包含有j的状态,也就是说参观第i-1座城市的人一定>=参观i城市时候的人,并且i城市的人在i-1城市的一定有,然后大家可以用类似于归纳法的思想来证明这种思路是正确的。
不罗嗦了,直接上代码:
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std;
#define INFI (1<<10)+20
#define MIN -2139062144
int N,M;
int dp[INFI],bonus[][],cost[];
int inter[][],temp[INFI]; inline int max(int a,int b)
{
if(a>b) return a;
return b;
}
int calculate(int k,int v)
{
int sieze[],num=,result=;
for(int i=;i<N;i++) if(k&(<<i)) sieze[++num]=i;
for(int i=;i<=num;i++)
{
result+=inter[sieze[i]][v];
for(int j=i+;j<=num;j++) result+=bonus[sieze[i]][sieze[j]];
}
return result-num*cost[v];
}
int DP()
{
int bit=<<N;
for(int i=;i<bit;i++) temp[i]=;
for(int i=;i<=M;i++)
{
for(int j=;j<bit;j++) dp[j]=MIN;
for(int j=;j<bit;j++)
{
int weight=calculate(j,i);
for(int k=j;k<bit;k=(k+)|j)
{
dp[j]=max(dp[j],temp[k]+weight);
}
}
for(int j=;j<bit;j++) temp[j]=dp[j];
}
int result=-;
for(int i=;i<bit;i++) result=max(result,temp[i]);
if(result<=) printf("STAY HOME.\n");
else printf("%d\n",result);
}
int main()
{ while(scanf("%d %d",&N,&M),(N||M))
{
for(int i=;i<=M;i++)
scanf("%d",&cost[i]); for(int i=;i<N;i++)
for(int j=;j<=M;j++)
scanf("%d",&inter[i][j]); for(int i=;i<N;i++)
for(int j=;j<N;j++)
scanf("%d",&bonus[i][j]); DP();
} return ;
}
状态压缩DP----HDU4049 Tourism Planning的更多相关文章
-
HOJ 2226&POJ2688 Cleaning Robot(BFS+TSP(状态压缩DP))
Cleaning Robot Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4264 Accepted: 1713 Descri ...
-
hoj2662 状态压缩dp
Pieces Assignment My Tags (Edit) Source : zhouguyue Time limit : 1 sec Memory limit : 64 M S ...
-
POJ 3254 Corn Fields(状态压缩DP)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4739 Accepted: 2506 Descr ...
-
[知识点]状态压缩DP
// 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前 ...
-
HDU-4529 郑厂长系列故事——N骑士问题 状态压缩DP
题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种. 分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快, ...
-
DP大作战—状态压缩dp
题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...
-
状态压缩dp问题
问题:Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Ev ...
-
BZOJ-1226 学校食堂Dining 状态压缩DP
1226: [SDOI2009]学校食堂Dining Time Limit: 10 Sec Memory Limit: 259 MB Submit: 588 Solved: 360 [Submit][ ...
-
Marriage Ceremonies(状态压缩dp)
Marriage Ceremonies Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu ...
-
HDU 1074 (状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...
随机推荐
-
实时的.NET程序错误监控产品Exceptionless
Exceptionless可以对ASP.NET, Web API, WebForms, WPF, Console, 和 MVC 应用提供错误监控.上传.报表服务.使用时需要在Exceptionless ...
-
Struts2入门(四)——数据输入验证
一.前言 1.1.什么是输入验证?为什么需要输入验证? 在上一篇文章中,我们学习了数据类型转换,我们提到了表示层数据处理的两个方法,也提到了用户输入数据需要进行类型转换才能得到我们想要的数据,那么,我 ...
-
在Salesforce中处理Xml的生成与解析
在Salesforce中处理Xml的生成与解析 1): Generate Xml private String ConvertAccountToXmlInfo(Account acc){ Dom.Do ...
-
C#winform如何最小化主窗口
1.如果不想让程序在任务栏中显示,请把窗体的属性ShowInTaskbar设置为false;2.如果想让程序启动时就最小化,请设置窗体的属性WindowState设置为Minimized.(Minim ...
-
linux ckconfig
linux自定义开机启动服务和chkconfig使用方法 linux自定义开机启动服务和chkconfig使用方法 1. 服务概述在linux操作系统下,经常需要创建一些服务,这些服务被做成shell ...
-
rtems总结
rtems 历史背景及现状 常用的api 和参数介绍 rtems_interrupt_enable rtems_interrupt_is_in_progress rtems_cache_flush_r ...
-
View和ViewGroup的区别 -- Touch事件处理
View.java源码: /frameworks/base/core/java/android/view/View.java View.java的 dispatchTouchEvent 方法: 经过一 ...
-
玩转Linux网络namespace-单机自环測试与策略路由
上周有厂商到公司測试,拿了一块据说非常猛的网络处理加速PCIe板卡,拎在手里沉甸甸的非常有分量,最让人意淫的是那4个万兆光口,于是我迫不及待的想要一览光口转发时那种看不见的震撼. 可是,仅凭4个光口怎 ...
-
TPFrame框架之robot模块的基本使用
经过几天的努力,基本功能版已经完成,有待大家验证... robot插件主要的功能是帮助我们写部分代码的基本,目前阶段已经实现后台curd数据管理的基本操作,更多功能待续... 1.首先下载robot插 ...
-
Axure 元件焦点的控制
讲解如何控制光标的位置,主要学习了以下三种场景: 1.点击邮箱或者密码时,光标分别自动定位到email.password的文本框处: 2.还有将密码对应的文本框的内容设置为密码的格式(····) 3. ...