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 行的所有的可以放的情况,那么对于 ...
随机推荐
- HTTP API 自动化测试从手工测试到平台的演变
不管是 Web 系统,还是移动 APP,前后端逻辑的分离设计已经是常态化,相互之间通过 API 调用进行数据交互.在基于 API 约定的开发模式下,如何加速请求 / 响应的 API 测试,让研发人员及 ...
- linux C 中的volatile使用
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存 ...
- PLSQL安装资料
一.plsql developer 注册码 plsql developer 10 注册码 product code :4v6hkjs66vc944tp74p3e7t4gs6duq4m4szbf3t38 ...
- 第三方APP集成微信登陆功能详解
授权后接口调用(UnionID) 通过code获取access_token 接口说明 通过code获取access_token的接口. 请求说明 http请求方式: GET https://api.w ...
- zoom to raster resolution
don't execute the ESRI's command, just find out and write codes to zoom to the raster resolution. H ...
- HDU1087 Super Jumping! Jumping! Jumping!(LIS)
题目意思: http://acm.hdu.edu.cn/showproblem.php? pid=1087 此题的意思求最长上升子序列的和. 题目分析: 在求最长上升子序列的时候,不在保存最长的个数, ...
- Java和C++里面的重写/隐藏/覆盖
首先,无关重载. 注:重载是同一个类的各个函数之间的.重写是父类子类之间的.Overload和Overwrite(也叫Override)的区别. 注意:Java里面区分重写(Override/Over ...
- [RxJS] `add` Inner Subscriptions to Outer Subscribers to `unsubscribe` in RxJS
When subscribers create new "inner" sources and subscriptions, you run the risk of losing ...
- setenv LD_LIBRARY_PATH
For most Linux binaries, NCL was built using gcc and gfortran. This may cause a dependency on a file ...
- 为什么不建议用Table布局
Tables的缺点 1.Table要比其它html标记占很多其它的字节.(延迟下载时间.占用server很多其它的流量资源.) 2.Tablle会阻挡浏览器渲染引擎的渲染顺序.(会延迟页面的生成速度, ...