**[POI2004]PRZ**
**考察内容:二进制子集遍历,DP转移**
#include <bits/stdc++.h>
using namespace std;
int n,W;
struct data1 {
int t,w;
}a[20];
int dp[(1<<20)],tt[(1<<20)],ww[(1<<20)];
int main() {
scanf("%d%d",&W,&n);
for(int i=1;i<=n;i++) {
scanf("%d%d",&a[i].t,&a[i].w);
}
int lim=(1<<n);
for(int i=0;i<lim;i++) {
for(int j=0;j<n;j++) {
if((i>>j)&1) {
tt[i]=max(tt[i],a[n-j].t);
ww[i]+=a[n-j].w;
}
}
}
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(int i=0;i<lim;i++) {
for(int j=i;j>=0;j=i&(j-1)) {
if(ww[i^j]<=W) {
dp[i]=min(dp[i],dp[j]+tt[i^j]);
}
if(!j) break;
}
}
printf("%d",dp[lim-1]);
return 0;
}
**互不侵犯**
**考察内容:状态矛盾处理,DP转移**
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int n,k;
LL dp[10][(1<<10)][100];
bool checkself(int x) {
if((x<<1) & x) return 0;
else return 1;
}
bool check(int x,int y) {
if(x & y) return 0;
else if((x<<1) & y) return 0;
else if((x>>1) & y) return 0;
else return 1;
}
int main() {
scanf("%d%d",&n,&k);
dp[0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int x=0;x<(1<<n);x++)
{
if(!checkself(x)) continue;
for(int y=0;y<(1<<n);y++)
{
if(!checkself(y)) continue;
if(check(x,y))
{
int numx=__builtin_popcount((unsigned)x);
for(int j=k;j>=numx;j--) {
dp[i][x][j]+=dp[i-1][y][j-numx];
}
}
}
}
}
LL ans=0;
for(int i=0;i<(1<<n);i++) {
ans+=dp[n][i][k];
// printf("%d ",dp[n][i][k]);
}
printf("%lld",ans);
return 0;
}