3305:有N中调料,M种配方。调料每种只能用一次,求能实现多少种配方。
即统计能划分出多少备选子集。
思路:本题代码参考自http://akheyun.blog.163.com/blog/static/13824927620102183300293/
核心思想是二进制表现。
x = (x - 1) & st 实现了子集遍历
比如 st=1110
1101 & 1110 = 1100
1011 & 1110 = 1010
1001 & 1110 = 1000
0111 & 1110 = 0110
0101 & 1110 = 0100
0011 & 1110 = 0010
0001 & 1110 = 0000
联想起求一个数的二进制中1有多少。
用到 x = (x-1) & x 这每次会使一个1变为0 用时可以小于O(n)
#include<iostream>
using namespace std;
#include<stdio.h>
#include<memory.h>
const int M = 1 << 16 + 1;
bool a[M];
int dp[M];
int solve(int st)
{
int i;
if (dp[st] != -1) return dp[st]; //已经计算过,直接返回
dp[st] = 0;
for (int x = st; x != 0; x = (x - 1) & st)
{
//不使用x能达到的配方数和使用x后配方数的最大值
if (a[x])
dp[st] = max(dp[st], solve(st - x) + 1);
}
return dp[st];
}
int main ()
{
int i, j, n, m, k, p;
while (scanf("%d%d", &n, &m) != EOF)
{
memset(a, false, sizeof(a));
memset(dp, -1, sizeof(dp));
for (i = 0; i < m; i++)
{
scanf("%d", &k);
j = 0;
while (k--)
{
scanf("%d", &p);
j += (1 << (p - 1)); //每种配方用2进制表示
}
a[j] = 1;
}
//初始全为1传入
printf("%d\n", solve((1 << n) - 1));
}
}
分享到:
相关推荐
zoj网站中多个练习的c++解答,文件名即为题目序号。经本人测试可以使用,主要为动态规划方面的问题,希望给初学者提供帮助。
ZOJ完全解题报告,喜欢ACM的同学,欢迎下载
zoj 1140-zju 2433 简单题的部分答案 都是可以正确通过的,简洁易懂
zoj 3590 -3+1.md
ZOJ题解集合-截至2835。共1244个文件,C/C++,有重复
ZOJ 1055 Oh, Those Achin Feet.bfs求最短路径.
zoj 3212 K-Nice.md
ZOJ解题报告ZOJ解题报告ZOJ解题报告ZOJ解题报告
zoj 2561 Order-Preserving Codes.md
zoj题目简单归类zoj题目简单归类zoj题目简单归类
NULL 博文链接:https://weitch.iteye.com/blog/1006972
acm中zoj1002的可运行C++程序
包含了zoj700多道题目的源代码,在做题时可以参考
Problem Arrangement zoj 3777
ZOJ题目答案源码
学习ACM程序设计的朋友一定要看,这是训练必备的POJ ZOJ题目分类及解题思路
一个非常非常非常非常实用的zoj结题代码
最新版硬件信息查询工具EVEREST Ultimate Edition Code:HJ8ZOJ-H307UX-0AA9RF-XFTD007
浙大ZOJ题目分类,可以让你更方便快速锁定那你想要联系的题目,是自己快速提高·
zoj 1003 c语言的,要写这么多描述吗。。