题目链接:http://acm.csust.edu.cn/problem/2007
博客园食用链接:https://www.cnblogs.com/lonely-wind-/p/13395416.html
Description

烧烤真的很好吃唉!集训队的团建除了佰烧,下馆子就是烧烤啦!

这天集训队一群毒瘤想出去吃烧烤,这里一共有nnn个烧烤店,编号1,2,...,n1,2,...,n1,2,...,n,这nnn个烧烤店中有mmm个特殊的烧烤店,初始时大家在1号烧烤店,他们想尝试其中至少kkk个不同的特殊的烧烤店。从任意两个烧烤店x,yx,yx,y走过去消耗的体力值都为111,注意你在当前的烧烤店停留一次也会消耗111点体力值。mp[i][j]mp[i][j]mp[i][j]表示从烧烤店iii到jjj的方案数。问他们恰好消耗QQQ点体力值且能品尝到至少kkk个不同的特殊烧烤店的方案数。数据保证11号烧烤店不是特殊的烧烤店。答案可能很大,输出模201908022019080220190802后的值。

Input
第一行五个整数,分别表示n,m,k,Qn,m,k,Qn,m,k,Q。

接下来一行mmm个整数aia_iai​表示特殊烧烤店的编号。

接下来一个nnn行nnn列的矩阵mpmpmp,意义如题。

1≤n,Q≤50,0≤m,k≤10,0≤mp[i][j]≤10001\leq n,Q\leq 50,0\leq m,k\leq 10,0\leq mp[i][j]\leq10001≤n,Q≤50,0≤m,k≤10,0≤mp[i][j]≤1000

Output
输出一行一个整数表示答案。

Sample Input 1
5 1 1 4
5
2 1 0 0 0
3 1 1 0 0
4 1 0 1 0
5 1 0 0 1
6 1 0 0 0

Sample Output 1
1

Sample Input 2
1 0 0 10
26

Sample Output 2
14277670

Sample Input 3
11 2 2 10
6 11
1 1 0 0 0 0 1 0 0 0 0
2 1 1 0 0 0 1 0 0 0 0
3 1 0 1 0 0 1 0 0 0 0
4 1 0 0 1 0 1 0 0 0 0
5 1 0 0 0 1 1 0 0 0 0
6 1 0 0 0 0 1 0 0 0 0
7 1 0 0 0 0 1 1 0 0 0
8 1 0 0 0 0 1 0 1 0 0
9 1 0 0 0 0 1 0 0 1 0
10 1 0 0 0 0 1 0 0 0 1
11 1 0 0 0 0 1 0 0 0 0
Sample Output 3
2

Hint

对于样例1:你只有一种走法能在规定体力消耗内吃到至少一个特殊烧烤店:1->2->3->4->5,方案数为1∗1∗1∗1=11 * 1 * 1 * 1=11∗1∗1∗1=1

对于样例2:要求吃到至少0个特殊烧烤店,也就是说你可以一个特殊烧烤店都不去,方案数为26^10 mod 20190802 =14277670

emmm,这道题挺好想的QAQ,至少现在看来是这样的。

看题目的数据范围,我们很容易知道用状压DP来解决,我们状压m个特殊的店于是就有了dp[1<<11]dp[1<<11]dp[1<<11],考虑到要恰好消耗QQQ点体力,所以我们要再加上一维,就变成了了dp[1<<11][55]dp[1<<11][55]dp[1<<11][55],但还有问题没有解决,也就是最后停留的点可能是1−n1-n1−n中的任意一点,所以我们还要再加上一维停留点:dp[1<<11][55][55]dp[1<<11][55][55]dp[1<<11][55][55]。计算一下空间,发现差不多了,应该不用再加了

接下来就是状态转移了,其中上面所说的三维肯定要枚举的,我们直接枚举上一个状态,然后再枚举上一个状态的最终停留点,再枚举上一个点所消耗的体力,那么要做状态转移的话肯定还要加上现在要去的点,于是就有了以下代码段:

dp[0][0][1]=1;
for (int i=0; i<(1<<m); i++) {for (int last=1; last<=n; last++) {if (vis[last] && !judge(i,1<<(vis[last]-1))) continue;//vis记录的是特殊点的编号,如果上一个点是特殊点,那么一定不会和上一个特殊点状态集矛盾for (int pw=0; pw<q; pw++) {if (!dp[i][pw][last]) continue;//小优化for (int now=1; now<=n; now++) {if (!mp[last][now]) continue;//小优化/*DP*/}}}
}

然后计算一波时间复杂度。。。O(2000∗50∗50∗50)O(2000*50*50*50)O(2000∗50∗50∗50),emmm,让我冷静一波,感觉似乎不能优化了啊,想法也应该没什么毛病,没办法了,只能硬着头皮刚一波再说了,说不定数据跑不满(水)呢,于是就有了以上的小优化。

接下来我们考虑转移,对于转移,应该有两种方式,第一个是现在要去的点为特殊点的时候,另一个就是非特殊点的时候,那么就有了一下转移方程:

if (vis[now]) {int sta=i|(1<<(vis[now]-1));dp[sta][pw+1][now]=(dp[sta][pw+1][now]+dp[i][pw][last]*mp[last][now])%mod;
}
else dp[i][pw+1][now]=(dp[i][pw+1][now]+dp[i][pw][last]*mp[last][now])%mod;

最后枚举一下最终状态和落脚点就行了。。。然后你就会发现。。你似乎过不了样例????

感觉天衣无缝啊,冷静分析一波。似乎体力的枚举不应该在里面,每次枚举消耗一个体力的时候应该跑完整个图的,那么也就是说体力的枚举应该放在最外面,然后trytrytry一波。。。。AC!妈妈,我终于会DP了QAQ

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int mod=20190802;ll dp[1<<11][55][55];//状态为sta,消耗q点体力,当前点为x号点的方案数
int b[100],mp[55][55],ok[1<<11];
int vis[55];int digt(int x)
{int ans=0;while (x){if (x&1) ans++;x>>=1; }return ans;
}void pre_oksta(int m,int k)
{for (int i=0; i<(1<<m); i++){int nb=digt(i);if (nb>=k) ok[i]=1;}
}int judge(int x,int y)
{for (int i=0; i<=10; i++)if (!(x&(1<<i)) && (y&(1<<i))) return 0;return 1;
}int main(int argc, char const *argv[])
{int n,m,k,q;scanf ("%d%d%d%d",&n,&m,&k,&q);for (int i=1; i<=m; i++) scanf ("%d",&b[i]),vis[b[i]]=i;for (int i=1; i<=n; i++)for (int j=1; j<=n; j++)scanf ("%d",&mp[i][j]);pre_oksta(m,k);dp[0][0][1]=1;for (int pw=0; pw<q; pw++){//枚举体力for (int i=0; i<(1<<m); i++){//枚举上一个状态for (int last=1; last<=n; last++){//枚举上一个落脚点if (vis[last] && !judge(i,1<<(vis[last]-1))) continue;if (!dp[i][pw][last]) continue;for (int now=1; now<=n; now++){//枚举现在要去的if (!mp[last][now]) continue;if (vis[now]){int sta=i|(1<<(vis[now]-1));dp[sta][pw+1][now]=(dp[sta][pw+1][now]+dp[i][pw][last]*mp[last][now])%mod;} else dp[i][pw+1][now]=(dp[i][pw+1][now]+dp[i][pw][last]*mp[last][now])%mod;}}}}ll ans=0;for (int i=0; i<(1<<(m+1)); i++){if (!ok[i]) continue;for (int j=1; j<=n; j++)ans=(ans+dp[i][q][j])%mod;}printf("%lld\n",ans);return 0;
}

CSUST 2007-我爱吃烧烤(状压DP)相关推荐

  1. CSUSTOJ 我爱吃烧烤 (状压dp)

    题目链接 大概意思就是Q的体力,n个烧烤店,m个特殊的,要去至少k个. 告诉了我们各个点的到达方案数的情况下,求解恰好Q体力且经过至少K个特殊烧烤店的方案数. 问题分析: n很小,但有50,直接状态压 ...

  2. CSUST 2007 我爱吃烧烤 (状压dp)

    链接: 我爱吃烧烤 题意: 总共 n 家烧烤店,有 m 家特殊烧烤店,从 i 到 j 号烧烤点有 mp [ i ] [ j ] 种方案,消耗一点体力值,问消耗 q 点体力值且至少经过 k 家特殊烧烤店 ...

  3. CSUST 2007 我爱吃烧烤 题解(状压dp)

    题目链接 题目大意 总共 n 家烧烤店,有 m 家特殊烧烤店,从 i 到 j 号烧烤点有 mp [ i ] [ j ] 种方案,消耗一点体力值,问消耗 q 点体力值且至少经过 k 家特殊烧烤店的方案数 ...

  4. P1433 吃奶酪(状压dp)

    洛谷 / 题目列表 / 题目详情 P1433 吃奶酪 提交 23.28k 通过 9.30k 时间限制 1.00s 内存限制 125.00MB 题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问 ...

  5. 【每日一题】洛谷 p1433 吃奶酪 状压dp

    - [P1433 吃奶酪](https://www.luogu.com.cn/problem/P1433) 换一种类型,这次求长度最小值,(n<15)接着状压 题目:房间里放着 nn 块奶酪.一 ...

  6. 刷题周记(九)——#状压DP:最短Hamilton路径、小国王(互不侵犯)、玉米田(Corn Fields G)、愤怒的小鸟、吃奶酪、炮兵阵地、宝藏 #区间DP:清空字符串#DP:关灯问题II

    文章目录 --2020年12月20日(周日)------------------ 状压DP 一.最短Hamilton路径(模板题) 二.玉米田(P1879 [USACO06NOV]Corn Field ...

  7. 【状压DP】吃货JYY(luogu 6085)

    正题 luogu 6085 题目大意 给你一个无向图,其中有一些边是必须走的,问你从1开始走,经过所有必须走的边,然后回到1的最短路径 解题思路 n很小,可以先用Floyd跑出两个点之间的最短路 然后 ...

  8. [蓝桥杯][算法提高VIP]Sharing Chocolate(状压dp记忆化搜索)

    题目描述 每天,巧克力在它的许多形式上被全世界数百万人分享.它是一个真正普遍的糖果,实际上在世界上每个国家都能得到. 你发现唯一比吃巧克力更好的事情是把它分享给朋友.不幸的是,你的朋友非常挑剔,有着不 ...

  9. Codeforces ----- Kefa and Dishes [状压dp]

    题目传送门:580D 题目大意:给你n道菜以及每道菜一个权值,k个条件,即第y道菜在第x道后马上吃有z的附加值,求从中取m道菜的最大权值 看到这道题,我们会想到去枚举,但是很显然这是会超时的,再一看数 ...

最新文章

  1. 让隔壁同事哇塞的IDEA主题!
  2. python比java简单好学-是不是Python比Java更容易学,更容易就业?
  3. JQuery源码-------JQuery中数值型变量的判断isNumeric
  4. 【CV】语义分割:最简单的代码实现!
  5. mysql b 树 b树_MySQL B树和B+树的区别
  6. 各项兼容坑的记录-持续更新
  7. 从框架源码中学习结构型设计模式
  8. 解密诡异并发问题的幕后黑手:可见性问题
  9. Scorm标准学习——Scorm RTE API与数据模型
  10. 甭给《程序员》把脉——你不是主编
  11. python计算传入数字参数的和_Python基础_6
  12. JavaScript:正则表达式 分组
  13. Linux 下构建域名服务器
  14. 《系统集成项目管理工程师》必背81-100题
  15. 【题解】LuoGu1512:伊甸园日历游戏
  16. 介绍PS工具“仿制图章工具”和“图案图章工具”
  17. Power bi 3.22 切片器
  18. Cesium加载面状geojson数据,并拉伸一定的高度。
  19. [Linux] SPI 设备驱动模型(以 Ad714x CapTouch 驱动分析)
  20. python处理excel实例编程_python处理Excel的简单示例

热门文章

  1. Android:logo
  2. 多版本node安装相关知识
  3. 北大c语言百度云资源,北大C语言讲义.pdf
  4. css display:grid布局
  5. 计算机专业助我成长作文600,资助助我成长作文
  6. http请求报错SSLError: HTTPSConnectionPool:Max retries exceeded with url
  7. 华为中央软件院编译器与编程语言实验室人才招募
  8. 怎么在计算机网络广播中发话,如何用电脑发网络传真?手把手教大家具体操作步骤...
  9. linux 文件夹的作用是什么,Linux个文件夹的作用及含义
  10. C/S模式和B/S模式