链接: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[j] 表示到达状态j时的最小花费,也就是执行了某些指令的最小花费,最后答案为dp[(1< 代码:
#include