zoj3777(状态压缩)
题目阐述:
给定n个座位,n个人,每个人可以做n个位置中的任意一个,P[i][j]代表第i个人做第j个位置获得的分数,求有多少种排列方式使得获得的分数大于等于M。
这道题跟数位dp的思想很像,都是穷举可能的方式,不过数位DP由于前缀的影响可以记忆化,这道题由于n较小,可以直接状态压缩.
定义状态d[i][s][t]代表已经放了i个座位,放的人数集合为s,获得分数为t的排列的数量。
然后每次暴力枚举每个位置可能会放的人
d[i][s | (1 << j)][t+ p[j][i]] +=d[i-1] [s] [t];
重点是如何实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 13
using namespace std;
int d[<<(maxn)][]; //表示到达状态s时产生的最大能量
int n,m;
int P[maxn][maxn];
int ans;
void init()
{
ans=;
memset(d,,sizeof(d));
}
//GCD
//求最大公约数
//O(logn)
int gcd(int a, int b)
{
if (b == )
return a;
else
return gcd(b, a%b);
}
int isok(int i)
{
int t=;
while(i)
{
if(i&) t++;
i>>=;
}
return t;
}
void solve()
{
int tot=(<<n)-;
d[][]=; //其实可以理解成d[-1][0][0],否则下面就需要特殊处理i等于0
for(int i=;i<n;i++) //代表第i个位置
{
for(int s=;s<=tot;s++) //遍历所有状态
{
if(isok(s)!=i) continue ;//检测哪些是前i-1个位置的状态
for(int t=;t<=m;t++) //遍历所有获得的分数
{
if(!d[s][t]) continue; //检测哪些是前i-1个位置获得的分数
for(int j=;j<n;j++) //枚举第i个位置可能放的人
{
if( s & (<<j) ) //检测前i-1个位置是否放过
continue;
int state= s | (<<j);
int MM=min(m,t+P[j][i]);
d[state][MM]+=d[s][t];
}
}
}
}
ans=d[tot][m];
} int main()
{
// freopen("test.txt","r",stdin);
int fac[maxn];
fac[]=;
for(int i=;i<maxn;i++)
fac[i]=fac[i-]*i;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=;i<n;i++)
for(int j=;j<n;j++)
{
scanf("%d",&P[i][j]);
}
solve();
int d = gcd(fac[n], ans);
if (ans == )
printf("No solution\n");
else
printf("%d/%d\n", fac[n]/d, ans/d);
}
return ;
}
bfs实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#define maxn 13
using namespace std;
int d[<<(maxn)][]; //表示到达状态s时产生的最大能量
int n,m;
int P[maxn][maxn];
int ans;
int gcd(int a, int b)
{
if (b == )
return a;
else
return gcd(b, a%b);
} int bit(int i)
{
int t=;
while(i)
{
if(i&) t++;
i>>=;
}
return t;
}
struct node
{
int s,t,cnt=;
};
int visit[<<maxn][];
void bfs()
{
queue < node > que;
memset(visit,,sizeof(visit));
int tot=(<<n)-;
node start,last;
start.s=; start.t=;
start.cnt=;
que.push(start);
visit[start.s][start.t]=;
d[][]=;
while(!que.empty())
{
node cur=que.front();
que.pop();
for(int i=;i<n;i++)
{
if(cur.s & (<<i))
continue;
node next ;
next.s= cur.s | (<<i);
next.cnt=cur.cnt+;
next.t= min(m,cur.t+P[i][cur.cnt]); //将第i个人放在当前位置,然后才会加1
d[next.s][next.t] += d[cur.s][cur.t];
if(visit[next.s][next.t]) //保证只进队一次
continue;
que.push(next);
visit[next.s][next.t]=;
}
}
ans=d[tot][m];
} int main()
{
// freopen("test.txt","r",stdin);
int fac[maxn];
fac[]=;
for(int i=;i<maxn;i++)
fac[i]=fac[i-]*i;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ans=;
memset(d,,sizeof(d));;
for(int i=;i<n;i++)
for(int j=;j<n;j++)
{
scanf("%d",&P[i][j]);
}
bfs();
int d = gcd(fac[n], ans);
if (ans == )
printf("No solution\n");
else
printf("%d/%d\n", fac[n]/d, ans/d);
}
return ;
}
zoj3777(状态压缩)的更多相关文章
- POJ 3254. Corn Fields 状态压缩DP (入门级)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9806 Accepted: 5185 Descr ...
- HDU 3605:Escape(最大流+状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...
- [HDU 4336] Card Collector (状态压缩概率dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336 题目大意:有n种卡片,需要吃零食收集,打开零食,出现第i种卡片的概率是p[i],也有可能不出现卡 ...
- HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)
题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由 ...
- codeforces B - Preparing Olympiad(dfs或者状态压缩枚举)
B. Preparing Olympiad You have n problems. You have estimated the difficulty of the i-th one as inte ...
- NOIP2005过河[DP 状态压缩]
题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...
- vijos1426兴奋剂检查(多维费用的背包问题+状态压缩+hash)
背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动 ...
- hoj2662 状态压缩dp
Pieces Assignment My Tags (Edit) Source : zhouguyue Time limit : 1 sec Memory limit : 64 M S ...
- poj3254 状态压缩dp
题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法. 分析:假如我们知道第 i-1 行的所有的可以放的情况,那么对于 ...
随机推荐
- 【组合数模板】HDU 6114 Chess
http://acm.hdu.edu.cn/showproblem.php?pid=6114 [思路] 就是求C(m,n) [板] #include<iostream> #include& ...
- JAVA自定义监听器的示例代码
JAVA用户自定义事件监听完整例子 JAVA用户自定义事件监听完整例子- —sunfruit 很多介绍用户自定义事件都没有例子,或是例子不全,下面写了一个完整的例子,并写入了注释以便参考,完整 ...
- 【Ural1297】Palindrome(后缀数组)
题意:求一个字符串的最长回文子串 n<=1000 思路:这是一道论文题 需要注意的细节: 1.奇偶分类 2.中间的分割符与最后的附加字母都是最小值,但两者不能相同,否则height可能会出现问题 ...
- 哀悼改变全站颜色为灰色CSS代码收藏
<style type="text/css"> *{ filter:progid:DXImageTransform.Microsoft.BasicIma ...
- sed命令解析[转载]
1.简介 sed是非交互式的编辑器.它不会修改文件,除非使用shell重定向来保存结果.默认情况下,所有的输出行都被打印到屏幕上. sed编辑器逐行处理文件(或输入),并将结果发送到屏幕.具体过程如下 ...
- Codeforces Manthan, Codefest 18 (rated, Div. 1 + Div. 2) D,E
D. Valid BFS? time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- MySQL基础架构
前段时间订阅了<Mysql实战45讲>(从原理到实战),新的一年为自己充充电.对于这部分内容,我所知道的只来源于我大学里学习的课程<数据库原理>,在大学里学习的只是简单的查询, ...
- try catch finally执行顺序 (return / 变量覆盖)
finally有return 始终返回finally中的return 抛弃 try 与catch中的return 情况1:try{} catch(){}finally{} return x; try{ ...
- 报错:An error occurred at line: 22 in the generated java file The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory
org.apache.jasper.JasperException: Unable to compile class for JSP: An error occurred at line: 22 in ...
- Ubuntu系统U盘安装以及降内核
由于项目需要,要用U盘制作一个Linux系统,支持EFI启动,并且内核版本要求是2.6.35.6.所以在选系统的时候,就必须要选安装文件里面带有EF I目录,并且该目录下面有BOOTx64.EFI和g ...