标签:void 图片 分析 考试 它的 位置 pac 解决 pre
一道状压DP(不会啊啊啊啊)
1 #include<fstream> 2 #define M 1000000007 3 #define cin fin 4 #define cout fout 5 using namespace std; 6 ifstream fin("count.in"); 7 ofstream fout ("count.out"); 8 int a[21],f[1<<21][21],t[1<<21]; 9 int n,m,k; 10 void take() //计算所有集合中1的个数 也就是选取的个数 11 { 12 for (int i=0;i<=(1<<n)-1;i++) 13 { 14 int ii=i; 15 while (ii) 16 { 17 t[i]++; 18 ii-=(ii&(-ii)); //(ii&(-ii))找到最后的1位置,然后减去 19 } 20 } 21 } 22 int main () 23 { 24 ios::sync_with_stdio(false); //cin优化 25 cin>>n>>m>>k; 26 for (int i=1,u,v;i<=m;i++) 27 { 28 cin>>u>>v; 29 a[u]|=(1<<(v-1)); //用二进制,来反应它的冲突 例: 30 } // 首先数组为 00000 31 take(); // 现在与3冲突了 00100 第三位 1 32 f[0][0]=1; // 又与 4 冲突了 01100 第四位变1 33 for(int i=0;i<=(1<<n)-1;i++) //所以这就表示出来了,当前数u与其他数的冲突情况 34 for(int j=0;j<=k;j++) 35 if(f[i][j]) 36 for(int x=1;x<=n;x++) 37 if((i&(1<<(x-1)))==0) // 表示当前集合与要变的位置没有变过 38 /*因为t记录的是(上面)t[i&a[x]]为冲突个数*/if(j+t[i&a[x]]<=k) //例 1010 x=2 1010 & 0100 无改变 39 f[i|(1<<(x-1))][j+t[i&a[x]]]=(f[i|(1<<(x-1))][j+t[i&a[x]]]+f[i][j])%M; 40 int ans=0; 41 for (int i=0;i<=k;i++) 42 ans=(ans+f[(1<<n)-1][i])%M; 43 cout<<ans; 44 }
标签:void 图片 分析 考试 它的 位置 pac 解决 pre
原文地址:https://www.cnblogs.com/zjzjzj/p/10327987.html