题目大意

N头牛,M个谷仓,每个牛c都有它喜欢的若干个谷仓,现在要将这N头牛安排进谷仓,使得每个牛都位于它喜欢的谷仓,而每个谷仓只能有一头牛。求安排的方案总数。N, M <= 20

题目分析

将M个谷仓视为一个整数的M个位,位i为1表示谷仓i被牛占用,否则表示谷仓i没有被牛占用。用状态 dp[i][j] 表示前i头牛安排进谷仓,使得谷仓占用情况形成整数j,所有的方案总数,那么有递推公式: 
dp[i+1][j | 1 << k] = dp[i+1][j | 1 << k] + dp[i][j],其中j的第k位为0(放置两头牛都占用谷仓k),且k为第i+1头牛喜欢的某个谷仓。 
    由于dp[i+1][...]只和dp[i][...]有关,因此可以使用循环数组进行状态压缩。dp[i&1][...]表示前i头牛的情况,dp[(i-1)&1][...]表示前i-1头牛的情况。

实现(c++)

#include <iostream>
#include<stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_N 22
vector<int> gCowLikesBarn[MAX_N]; //存放牛i 喜欢的barns
//不超过20头牛,有牛位于barn k中,则第k位置为1,则用一个整数表示barn的使用情况。 不超过 1 << 22
//dp[i][j] 表示前i头牛,barn的占用情况构成数字j,则总的情形个数,则有递推公式
//dp[i+1][j | 1 << k] = dp[i+1][j | 1 << k] + dp[i][j],其中 j的二进制第k位上为0,否则存在重复,
//且k为第i+1头牛的一个喜欢的barn号 //dp[i+1][...] 只和 dp[i][...]有关,因此考虑使用滚动数组,优化空间。
int dp[2][1 << MAX_N]; int main(){
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++){
int p;
gCowLikesBarn[i].clear();
scanf("%d", &p);
for (int j = 1; j <= p; j++){
int barn;
scanf("%d", &barn);
gCowLikesBarn[i].push_back(barn - 1);
}
}
dp[0][0] = 1;
for (int i = 1; i <= n; i++){
memset(dp[i & 1], 0, sizeof(dp[i & 1])); //滚动数组的当前行(共两行)
for (int j = 0; j < (1 << m); j++){
if (dp[(i - 1) & 1][j] == 0) //如果前i-1头牛所在的barn构成j的方案总数为0,则j和第i头牛再构成的方案 不合法!
continue; for (int k = 0; k < gCowLikesBarn[i].size(); k++){ //dp[i+1][j | 1 << k] = dp[i+1][j | 1 << k] + dp[i][j]
if (((j >> gCowLikesBarn[i][k]) & 1) == 0){ //不能重复有牛
dp[i & 1][j | (1 << gCowLikesBarn[i][k])] += dp[(i - 1) & 1][j];
}
}
}
}
int count = 0;
//此时的dp[i][j]中存放了 n头牛所在的barn构成j的方案总数,全部加和
for (int i = 0; i < (1 << m); i++){
count += dp[n & 1][i];
}
printf("%d\n", count);
return 0;
}

最新文章

  1. 在&lt;s:iterator&gt;标签里给动态表格添加序号
  2. php 连接 mssql 常见的所有问题
  3. Codeforces 740C. Alyona and mex 思路模拟
  4. dubbo框架----初探索-配置
  5. Python 2.x闭包(enclosure)中的变量访问&amp;修改
  6. 最全的iOS面试题及答案-转载
  7. Android核心分析之二十七Android GDI 之SurfaceFlinger之动态结构示
  8. css引入讲解及media
  9. 高性能MySQL第2,3章性能相关 回顾笔记
  10. 刚买个炼狱蝰蛇1800dpi的下完驱动提示没有发现鼠标
  11. mix-blend-mode
  12. 181102 Windows下安装kivy(用python写APP)
  13. Feign源码解析系列-注册套路
  14. Linux核心命令
  15. 【kindle笔记】之 《犬夜叉》-2017-12-26
  16. 1、linux下对绝对路径和相对路径
  17. 微信小程序(微信应用号)组件讲解[申明:来源于网络]
  18. python利用unittest测试框架组织测试用例的5种方法
  19. mysql官网文档调试MYSQL资料 5.7
  20. vim复制粘贴常用命令

热门文章

  1. echart 地图
  2. JavaScrip——DOM操作(属性操作)
  3. 爱快AP-H1使用方法及排错
  4. Linux服务器同步时间
  5. 标准Drupal7安装中文翻译出错解决办法
  6. 关于Cocos2d-x中图集中图片的调用
  7. TensorFlow基础笔记(13) Mobilenet训练测试mnist数据
  8. JavaScript 学习笔记(三)
  9. 转载:Erlang 函数(Efficiency Guide)
  10. 初次使用ets