状态压缩动态规划
http://poj.org/problem?id=3254
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int mod=100000000;
const int maxn=12;
int dp[maxn+1][(1<<maxn)+1];
int num[maxn+1];
int n,m;
bool check(int i,int x)//检查第i行出现状态x是否合法
{
if((x&num[i])!=x)//很巧妙,判断第i行出现的状态x是否合法,为什么这么写,因为0的地方不能放牛,
//合法状态与原始状态0位且为0,原始状态1位的地方与合法状态对应位且都等于合法状态位上的数字
return 0;
if(x&(x>>1)||x&(x<<1))//不能有相邻的两个1
return 0;
return 1;
}
int main()
{
cin>>n>>m;
int x;
memset(num,0,sizeof(num));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>x;
if(x)
num[i]=num[i]|(1<<(j-1));//把每一行的状态保存到num[i]中去
}
int Max=(1<<m);
dp[0][0]=1;//注意这一句啊!
for(int i=1;i<=n;i++)//枚举每一行
{
for(int j=0;j<Max;j++)
{
if(!check(i,j))
continue;
for(int k=0;k<Max;k++)
if((j&k)==0)
{
dp[i][j]+=dp[i-1][k];
if(dp[i][j]>=mod)
dp[i][j]%=mod;
}
}
}
int ans=0;
for(int i=0;i<Max;i++)
{
ans+=dp[n][i];
if(ans>=mod)
ans%=mod;
}
cout<<ans;
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=3001
http://acm.hdu.edu.cn/showproblem.php?pid=4568
POJ 3311
http://acm.fzu.edu.cn/problem.php?pid=2093
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int INF = 0x7FFFFFFF;
const int maxn = 1 << 16;
int T, n, m, dp[maxn], f[maxn], x, y;
queue<int> p;
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) f[i] = 0;
for (int i = 1; i < (1 << n); i++) dp[i] = INF;
while (m--)
{
scanf("%d%d", &x, &y);
f[x - 1] |= 1 << (y - 1);
f[y - 1] |= 1 << (x - 1);
}
//for(int i=0;i<n;i++) cout<<f[i]<<" ";cout<<endl;
for (int i = 0; i < n; i++) if (!f[i]) f[i] = 1 << i;
while (!p.empty()) p.pop(); p.push(0);
while (!p.empty())
{
int q = p.front(); p.pop();
int now = 0;
for (int i = 0; i < n; i++) if ((q&f[i]) == f[i]) now |= 1 << i;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (dp[now | (1 << i) | (1 << j)] > dp[q] + 1)
{
dp[now | (1 << i) | (1 << j)] = dp[q] + 1;
p.push(now | (1 << i) | (1 << j));
}
}
}
}
int k = (1 << n) - 1, ans = dp[k];
//for(int i=0;i<n;i++) cout<<(k ^ (1 << i))<<dp[k ^ (1 << i)]<<" ";cout<<endl;
for (int i = 0; i < n; i++) ans = min(ans, dp[k ^ (1 << i)]);
if (ans == INF) printf("-1\n"); else printf("%d\n", ans);
}
return 0;
}