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 行的所有的可以放的情况,那么对于 ...
随机推荐
- BZOJ4551 - [TJOI2016]树
Portal Description 给出一棵\(n(n\leq10^5)\)个点的以\(1\)为根的有根树,进行\(Q(Q\leq10^5)\)次操作: 标记一个点\(x\). 询问\(x\)的祖先 ...
- 洛谷P1432 倒水问题
题目背景 In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with th ...
- 565. Array Nesting
Problem statement: A zero-indexed array A consisting of N different integers is given. The array con ...
- 【组合数模板】HDU 6114 Chess
http://acm.hdu.edu.cn/showproblem.php?pid=6114 [思路] 就是求C(m,n) [板] #include<iostream> #include& ...
- JavaScript 将行结构数据转化为树结构数据源(高效转化方案)
js接收到后台的数据如下 /// 部门信息 var departRows = [{ parentDepartId: 'root', departId: 'DC', departName: '集团' } ...
- POJ 2391 floyd二分+拆点+最大流
Ombrophobic Bovines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20904 Accepted: 4 ...
- Codeforces 659B Qualifying Contest【模拟,读题】
写这道题题解的目的就是纪念一下半个小时才读懂题...英文一多读一读就溜号... 读题时还时要静下心来... 题目链接: http://codeforces.com/contest/659/proble ...
- P1396 营救 洛谷
https://www.luogu.org/problem/show?pid=1396 题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起 ...
- Java 基础部分知识复习
面向对象的特征: 继承.封装和多态 封装 : 把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象去操作.对不可信的信息进行隐藏. 继承: 它可以使用现有类的功能,并在无需重新编 ...
- Java函数式接口Consumer
Consumer是java8提供的函数式接口之一,意思为消费者,接受参数而不返回值 void accept(T t); default Consumer<T> andThen(Consum ...