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 4597
题目大意: 两人轮流从两堆牌从抽取最顶端或者最底部的牌,得到的分数加到自己身上,问先拿牌的最多能得多少分 记忆化搜索,2堆牌的底和顶,有四种方法,根据四种方法来找到最优解 #include <c ...
- POJ 2391 Ombrophobic Bovines【二分 网络流】
题目大意:F个草场,P条道路(无向),每个草场初始有几头牛,还有庇护所,庇护所有个容量,每条道路走完都有时间,问所有奶牛都到庇护所最大时间最小是多少? 思路:和POJ2112一样的思路,二分以后构建网 ...
- 人生第一场CTF的解题报告(部分)
解题报告 濮元杰部分: 王者归来: 120 场景 小王入职了一段时间,最近有点无聊.Web安全项目不多,白天看着其他项目组的同事忙得热火朝天,小王有点坐不住了,这也许是新人都会有的想法,乐于助人.想到 ...
- JAVA自定义监听器的示例代码
JAVA用户自定义事件监听完整例子 JAVA用户自定义事件监听完整例子- —sunfruit 很多介绍用户自定义事件都没有例子,或是例子不全,下面写了一个完整的例子,并写入了注释以便参考,完整 ...
- CSS属性操作二
9.float属性 基本浮动规则 先来了解一下block元素和inline元素在文档流中的排列方式. block元素通常被现实为独立的一块,独占一行,多个block元素会各自新起一行,默认block元 ...
- IText 生成pdf,处理table cell列跨页缺失的问题
/** * 创建(table)PDF,处理cell 跨页处理 * @param savePath(需要保存的pdf路径) * @param pmbs (数据库查询的数据) ...
- CodeForces 597A Divisibility
水题. #include<iostream> #include<cstring> #include<cmath> #include<queue> #in ...
- 魔咒词典--hdu1880(字符串 暴力)
http://acm.hdu.edu.cn/showproblem.php?pid=1880 不要想其他的 暴力就能过 #include <iostream> #include < ...
- MySQL中的数据类型的长度范围和显示宽度(转)
长度范围是随数据类型就已经是固定的值,而显示宽度与长度范围无关. 以下是每个整数类型的存储和范围(来自MySQL手册) 类型 字节 最小值 最大值 (带符号的/无符号的) (带符号的/无符号的) TI ...
- Meteor package.js
在本章中,我们将学习如何创建自己的 meteor 包. 创建包 让我们添加在桌面上的新文件夹用来创建新的包.使用命令提示符窗口执行如下命令. C:\Users\Administrator\Deskto ...