链接:https://ac.nowcoder.com/acm/problem/21873
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
牛牛的计算机一共有m块内存,现在有n条指令,每条指令是一个01序列
如果指令的第i个字符为1,说明这条指令需要访问第i块内存
每条指令的执行代价为k^2, k为新访问内存的数量,即之前的指令都没有访问到的内存数量
你可以随意安排n条指令的执行顺序,求执行完所有指令的最小代价
输入描述:
第一行先输入一个整数n (1≤n≤201 \le n \le 201≤n≤20) 接下来每行输入一个01字符串,长度不超过20
输出描述:
输出一个整数
示例1
输入
复制
3 3 111 001 010
输出
复制
3
示例2
输入
复制
5 5 11101 00111 10101 00000 11000
输出
复制
9
示例3
输入
复制
3 4 1000 1100 1110
输出
复制
3
备注:
子任务1:n <= 5 子任务2:n <= 10 子任务3:无限制
dp[j]表示执行的指令状态为j时的最小代价
val[j]表示执行指令状态为j时已被访问的内存
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
int dp[(1<<20)+5],val[(1<<20)+5];
int sta[22];
char s[22];
int n,m;
int solve(int a,int b){
int ans=0;
for(int i=0;i<m;i++){
if((a&(1<<i))==0&&(b&(1<<i))) ans++;
}
return ans*ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",s);
for(int j=0;j<m;j++){
if(s[j]=='1') sta[i]=sta[i]|(1<<j);
}
}
memset(dp,INF,sizeof(dp));
dp[0]=0;
for(int j=0;j<(1<<n);j++){//枚举状态
for(int k=0;k<n;k++){//枚举指令
if(!(j&(1<<k))){
int ans=dp[j]+solve(val[j],sta[k]);
if(dp[j|(1<<k)]>ans){
dp[j|(1<<k)]=ans;
val[j|(1<<k)]=val[j]|sta[k];
}
}
}
}
printf("%d\n",dp[(1<<n)-1]);
return 0;
}