状压DP
状压 DP 是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。
例题
售货员的难题 洛谷1171
#include<bits/stdc++.h>
using namespace std;
int n,i,j,k,min1,a[25][25],f[1050000][25];
int main()
{
cin>>n;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
cin>>a[i][j];
memset(f,64,sizeof(f));
f[1][1]=0;
for (i=1;i<1<<n;i+=2)
{
for (j=1;j<=n;j++)
{
if (!(i>>(j-1)&1))
continue;
for (k=1;k<=n;k++)
{
if (j==k)
continue;
if (!(i>>(k-1)&1))
continue;
f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+a[k][j]);
}
}
}
min1=2147483647;
for (i=1;i<=n;i++)
min1=min(min1,f[(1<<n)-1][i]+a[i][1]);
cout<<min1<<'\n';
}
单词游戏 洛谷1278
#include<bits/stdc++.h>
using namespace std;
long long n,i,max1,f[1<<16][5];
string s;
struct ff{
long long bg,ed,len;
}a[20];
long long sc(long long x,long long y)
{
if (f[x][y]!=-1)
return f[x][y];
long long s=0;
for (int i=0;i<n;i++)
if ((y==a[i].bg)and(!((1<<i)&x)))
s=max(s,sc(x|1<<i,a[i].ed)+a[i].len);
f[x][y]=s;
return s;
}
int change(char ch)
{
if (ch=='A')
return 0;
if (ch=='E')
return 1;
if (ch=='I')
return 2;
if (ch=='O')
return 3;
if (ch=='U')
return 4;
}
int main()
{
cin>>n;
for (i=0;i<n;i++)
{
cin>>s;
a[i].bg=change(s[0]);
a[i].ed=change(s[s.length()-1]);
a[i].len=s.length();
}
for (i=0;i<n;i++)
{
memset(f,-1,sizeof(f));
max1=max(max1,sc(1<<i,a[i].ed)+a[i].len);
}
cout<<max1<<'\n';
}
平板涂色 洛谷1283
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,i,j,k,s,to,min1,f[1<<17][21];bool ff;
struct sc{
ll ax,ay,bx,by,c;
}a[40];
vector<ll>b[17];
int main()
{
cin>>n;
for (i=0;i<n;i++)
cin>>a[i].ax>>a[i].ay>>a[i].bx>>a[i].by>>a[i].c;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (i!=j)
{
if ((a[i].bx==a[j].ax)and((a[i].ay<=a[j].ay)and(a[i].by>=a[j].ay)or(a[i].ay<=a[j].by)and(a[i].by>=a[j].by)or(a[i].ay>=a[j].ay)and(a[i].by<=a[j].by)))
b[j].push_back(i);
}
memset(f,64,sizeof(f));
for (i=0;i<=20;i++)
f[0][i]=1;
for (i=0;i<(1<<n);i++)
{
for (j=0;j<n;j++)
{
if (!((1<<j)&i))
continue;
ff=true;s=1000000;
for (k=0;k<b[j].size();k++)
{
to=b[j][k];
if ((!((1<<to)&i)))
{
ff=false;
break;
}
s=min(s,f[i^(1<<j)][a[to].c]+(!(a[to].c==a[j].c)));
}
if (ff)
{
for (k=1;k<=20;k++)
s=min(s,f[i^(1<<j)][k]+(!(a[j].c==k)));
f[i][a[j].c]=s;
}
}
}
min1=1000000;
for (i=1;i<=20;i++)
min1=min(min1,f[(1<<n)-1][i]);
cout<<min1<<'\n';
}
互不侵犯 洛谷1896
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,j,k,s,q,p,l,f[15][1050][105];
long long judge(long long x)
{
int k=0,s=0;
while (x>0)
{
if ((x%2==1)and(k==1))
return -1;
k=x%2;
s=s+k;
x=x/2;
}
if (s<=m)
return s;
else
return -1;
}
bool judge2(long long x,long long y)
{
int t2=0,w2=0;
while ((x>0)or(y>0))
{
int t=x%2;int w=y%2;
if ((t==1)and((w==1)or(w2==1)))
return true;
if ((w==1)and((t==1)or(t2==1)))
return true;
t2=t;w2=w;
x=x/2;y=y/2;
}
return false;
}
int main()
{
cin>>n>>m;
for (i=0;i<1<<n;i++)
{
q=judge(i);
if ((q!=-1)and(q<=m))
f[1][i][q]=1;
}
for (i=1;i<=n;i++)
for (j=0;j<1<<n;j++)
{
q=judge(j);
if (q==-1) continue;
for (k=0;k<1<<n;k++)
{
p=judge(k);
if ((p==-1)or(q+p>m)or(judge2(j,k))) continue;
for (l=q;l<=m-p;l++)
f[i][k][l+p]=f[i][k][l+p]+f[i-1][j][l];
}
}
for (i=0;i<1<<n;i++)
s=s+f[n][i][m];
cout<<s<<'\n';
}
炮兵阵地 洛谷2704
#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,k,l,ma,a[105],b[1050],f[5][1050][1050];
char ch;
int judge(int x)
{
int s=0,k=0,a=0,b=0;
while (x>0)
{
k=x%2;s+=k;
if ((k==1)and((a==1)or(b==1)))
return -1;
a=b;
b=k;
x=x/2;
}
return s;
}
int main()
{
cin>>n>>m;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
{
cin>>ch;
if (ch=='H')
a[i]=a[i]*2+1;
else a[i]=a[i]*2;
}
for (i=0;i<(1<<m);i++)
{
b[i]=judge(i);
if ((!(i&a[1]))and(b[i]!=-1))
f[1][i][0]=b[i];
}
for (i=0;i<(1<<m);i++)
if ((!(i&a[1]))and(b[i]!=-1))
for (j=0;j<(1<<m);j++)
if ((!(j&a[2]))and(b[j]!=-1)and(!(i&j)))
f[2][j][i]=max(f[2][j][i],f[1][i][0]+b[j]);
for (i=3;i<=n;i++)
for (j=0;j<(1<<m);j++)
if ((b[j]!=-1)and(!(j&a[i])))
for (k=0;k<(1<<m);k++)
if ((b[k]!=-1) and (!(k&a[i-1])) and (!(j&k)))
for (l=0;l<(1<<m);l++)
if ((b[l]!=-1) and (!(l&a[i-2])) and (!(j&l)) and (!(k&l)))
f[i%3][j][k]=max(f[i%3][j][k],f[(i-1)%3][k][l]+b[j]);
for (i=0;i<(1<<m);i++)
for (j=0;j<(1<<m);j++)
if ((b[i]!=-1)and(b[j]!=-1)and (!(i&j)))
ma=max(ma,f[n%3][i][j]);
cout<<ma<<'\n';
}
Little Pony and Harmony Chest
https://codeforces.com/contest/453/problem/B
#include<bits/stdc++.h>
using namespace std;
int n, m, i, j, k, x, y, t, mi, a[105], b[105], f[105][1 << 18], g[105][1<<18],c[105],d[105];
bool f2;
int main()
{
cin >> n;
for (i = 1; i <= n; i++)
cin >> a[i];
for (i = 2; i <= 60; i++)
{
for (j = 2; j <= i / 2; j++)
if (i % j == 0)
break;
if (j == i / 2 + 1)
b[++m] = i;
}
for (i = 1; i <= 60; i++)
for (j = 1; j <= m; j++)
if (i % b[j] == 0)
d[i] = d[i] ^ (1 << (j - 1));
memset(f, 0x3f, sizeof(f));
f[0][0] = 0;
for (i=1;i<=n;i++)
for (j = 0; j < 1 << m; j++)
for (k = 1; k <= a[i]*2; k++)
if ((d[k] & j) == d[k])
{
t = j ^ d[k];
if (f[i - 1][t] + abs(a[i] - k) < f[i][j])
{
f[i][j] = f[i - 1][t] + abs(a[i] - k);
g[i][j] = k;
}
}
mi = 1e11;
for (i = 0; i < 1 << m; i++)
if (f[n][i] < mi)
{
mi = f[n][i];
k = i;
}
for (i = n; i >= 1; i--)
{
c[i] = g[i][k];
x = g[i][k]; y = 1;
while (x > 1)
{
f2 = false;
while (x % b[y] == 0)
{
x = x / b[y];
f2 = true;
}
if (f2)
k = k ^ (1 << (y - 1));
y++;
}
}
for (i = 1; i < n; i++)
cout << c[i] << ' ';
cout << c[n] << '\n';
}
Another Sith Tournament
https://codeforces.com/contest/678/problem/E
#include<bits/stdc++.h>
using namespace std;
int n, i, j, k, l, b[1 << 19];
double a[20][20], f[1 << 19], ma;
int main()
{
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
cin >> a[i][j];
for (i = 0; i < 1 << n; i++)
{
k = i;
while (k > 0)
{
b[i] = b[i] + k % 2;
k = k / 2;
}
}
f[1] = 1;
for (i = 2; i <= n; i++)
for (j = 0; j < 1 << n; j++)
if (b[j] == i)
for (l = 1; l <= n; l++)
if (j & (1 << (l - 1)))
for (k = 1; k <= n; k++)
if (j & (1 << (k - 1)))
if (k != l)
f[j] = max(f[j], f[j ^ (1 << (l - 1))] * a[k][l] + f[j ^ (1 << (k - 1))] * a[l][k]);
printf("%.6f", f[(1<<n)-1]);
}
Binary Table
https://codeforces.com/contest/662/problem/C
#include<bits/stdc++.h>
using namespace std;
int n, m, i, j, k, s, ma; char ch;
int a[22][100005], f[22][1 << 21];
int main()
{
cin >> n >> m;
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
cin >> ch;
a[i][j] = ch - '0';
}
for (i = 1; i <= m; i++)
{
s = 0;
for (j = 1; j <= n; j++)
s = s * 2 + a[j][i];
f[0][s]++;
}
for (i = 1; i <= n; i++)
for (j = n; j >= 1; j--)
for (k = 0; k < 1 << n; k++)
f[j][k] = f[j][k] + f[j - 1][k ^ (1 << (i - 1))];
ma = 1e10;
for (i = 0; i < (1 << n); i++)
{
s = 0;
for (j = 1; j <= n; j++)
s = s + f[j][i] * min(j, n - j);
ma = min(ma, s);
}
cout << ma << '\n';
}
标签:std,int,状压,namespace,long,using,include,DP
From: https://www.cnblogs.com/ShadowAA/p/17320821.html