利用二进制枚举和状态压缩
利用二进制来表达选择的状态
例题:
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int ans=0;
for(int i=0;i<(1<<14);++i){
int tot_1=0;
int tot_0=0;
int num=2;
for(int j=0;j<14;++j){
if(i&(1<<j)){//判断 i从右数第j+1位是否为1
tot_1++;
num=num*2;
}
else {
tot_0++;
num-=1;
}
}
if(num==1 && tot_1==5 && tot_0==9){
ans++;
}
}
cout<<ans<<endl;
return 0;
}
x星球的盛大节日为增加气氛,用30台机光器一字排开,向太空中打出光柱。
安装调试的时候才发现,不知什么原因,相邻的两台激光器不能同时打开!
国王很想知道,在目前这种bug存在的情况下,一共能打出多少种激光效果?
显然,如果只有3台机器,一共可以成5种样式,即:
全都关上(sorry, 此时无声胜有声,这也算一种)
开一台,共3种
开两台,只1种
30台就不好算了,国王只好请你帮忙了。
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
long long ans;
int main(){
for(int i=0;i<(1<<30);i++){
int flag=1;
for(int j=1;j<30;j++){
if(i&(i>>1)){//没有相邻的1
flag=0;
break;
}
}
ans+=flag;
}
//ans=2178309;
cout<<ans;
return 0;
}
状态压缩
当元素数量比较小(不超过20)时,可以使用状态压缩
比如5个元素a,b,c,d,e 可以分别用1,2,4,8,16表示 则集合{b,c,d}可以用(01110)=14表示,这种方法经常使用与动态规划中
如果用传统的动态规划作法对5个元素则需要至少开5维数组,利用状态压缩则可以压缩进一维数组里。但同时注意这种方法并没有优化空间复杂度,只是相对的容易写出代码.
n个人在做传递物品的游戏,编号为1-n。
游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位;下一个人可以传递给未接过物品的任意一人。
即物品只能经过同一个人一次,而且每次传递过程都有一个代价;不同的人传给不同的人的代价值之间没有联系;
求当物品经过所有n个人后,整个过程的总代价是多少。
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int a[20][20];
int dp[1 << 16][20];
int main(){
memset(dp,0x3f,sizeof(dp));
int n;
cin >> n;
for(int i=0;i<n;i++){
dp[1 << i][i]=0;
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<(1 << n);i++){
for(int j=0;j<n;j++){
if(i & (1<<j)){
for(int k=0;k<n;k++){
if(!(i&(1<<k))){
dp[i | 1<<k][k]=min(dp[i|1<<k][k],dp[i][j]+a[j][k]);
}
}
}
}
}
int ans=INF;
for(int i=0;i<n;i++){
ans=min(ans,dp[(1<<n)-1][i]);
}
cout<<ans<<endl;
return 0;
}
// freopen("testdata.in", "r", stdin);