动态规划----状压dp|牛客练习题---21873(牛牛的计算机内存【状压dp】)

链接:https://ac.nowcoder.com/acm/problem/21873
来源:牛客网
题意:
牛牛的计算机一共有m块内存,现在有n条指令,每条指令是一个01序列
如果指令的第i个字符为1,说明这条指令需要访问第i块内存
每条指令的执行代价为k^2, k为新访问内存的数量,即之前的指令都没有访问到的内存数量
你可以随意安排n条指令的执行顺序,求执行完所有指令的最小代价
输入:

第一行先输入一个整数n,m(1 ≤ n ≤ 20) 接下来每行输入一个01字符串,长度不超过20

分析:
因为可以随意安排执行顺序,暴力就是20!,必然TLE,从记忆化搜索可以得到动态规划的做法
定义dp[i][j],表示执行完前i次后状态为j的最小代价,状态j是什么呢?就是将前i次选的i条指令的编号压缩成一个数j,比如j的二进制为(110),就代表前2次分别执行了编号为1和2的指令
定义val[i][j]表示到达dp[i][j]时,所选的指令所代表的字符串的状态,可以将每条指令看成一个二进制字符串,再将它压缩成十进制数表示状态,注意开滚动数组,否则要MLE
代码:
#include using namespace std; const int inf = 0x3f3f3f3f; int a[22],n,m,dp[2][1<<20],val[2][1<<20]; string s[22]; int cal(int x)//将二进制字符串压缩成十进制数 { int res = 0,b = 1; for(int i = 0; i < m; ++i,b <<= 1) res += (s[x][i]=='1' ? b : 0); return res; } int cal2(int a,int b)//计算a->b要花费的代价 { int res = 0; for(int i = 0; i < 22; ++i){ if((a & (1<>n>>m; memset(dp,inf,sizeof(dp)); for(int i = 0; i < n; ++i) cin>>s[i]; for(int i = 0; i < n; ++i){ a[i] = cal(i); dp[0][1<

【动态规划----状压dp|牛客练习题---21873(牛牛的计算机内存【状压dp】)】上面的代码更具逻辑性,考虑当执行了一些指令后,下一次必然执行还未执行的一条指令,定义dp[j] 表示到达状态j时的最小花费,也就是执行了某些指令的最小花费,最后答案为dp[(1< 代码:
#include using namespace std; const int inf = 0x3f3f3f3f; int n,m,a[22],dp[1<<20],val[1<<20]; char s[22]; int cal(int x)//将二进制字符串压缩成十进制数 { int res = 0,b = 1; for(int i = 0; i < m; ++i,b <<= 1) res += (s[i]=='1' ? b : 0); return res; } int cal2(int a,int b)//计算a->b要花费的代价 { int res = 0; for(int i = 0; i < 22; ++i){ if((a & (1<> n >> m; for(int i = 0; i < n; ++i) cin >>s,a[i] = cal(i); memset(dp,inf,sizeof(dp)); dp[0] = 0; for(int j = 0; j < (1< tep){ dp[j|(1<


    推荐阅读