牛牛的计算机内存(状压DP)
链接:https://ac.nowcoder.com/acm/problem/21873
来源:牛客网
题目描述
牛牛的计算机一共有m块内存,现在有n条指令,每条指令是一个01序列
如果指令的第i个字符为1,说明这条指令需要访问第i块内存
每条指令的执行代价为k^2, k为新访问内存的数量,即之前的指令都没有访问到的内存数量
你可以随意安排n条指令的执行顺序,求执行完所有指令的最小代价
如果指令的第i个字符为1,说明这条指令需要访问第i块内存
每条指令的执行代价为k^2, k为新访问内存的数量,即之前的指令都没有访问到的内存数量
你可以随意安排n条指令的执行顺序,求执行完所有指令的最小代价
输入描述:
第一行先输入一个整数n (1≤n≤201≤n≤20)
接下来每行输入一个01字符串,长度不超过20
输出描述:
输出一个整数
具体思路:
dp[i]表示i所对应的二进制中选了哪几行的最小花费。
val[i]表示i所对应的二进制中选了哪几行对应的访问了哪些内存
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 const int mod = 1e9+7; 6 const int maxn = 2e6+100; 7 int dp[maxn],val[maxn]; 8 int n,m; 9 int cal(char str[]) 10 { 11 int len=strlen(str); 12 int tmp=1; 13 int ans=0; 14 for(int i=len-1; i>=0; i--) 15 { 16 ans+=(str[i]-'0')*tmp; 17 tmp<<=1; 18 } 19 return ans; 20 } 21 char str[25]; 22 int f(int t1,int t2) 23 { 24 int ans=0; 25 for(int i=0; i<=20; i++) 26 { 27 if(((t1&(1<<i))==0)&&(t2&(1<<i))) 28 ans++; 29 } 30 return ans*ans; 31 } 32 int a[maxn]; 33 int main() 34 { 35 memset(dp,inf,sizeof(dp)); 36 dp[0]=0; 37 scanf("%d %d",&n,&m); 38 for(int i=0; i<n; i++) 39 { 40 scanf("%s",str); 41 a[i]=cal(str);// 因为比较的时候是按照十进制比较的,所以先转换成二进制 42 } 43 int maxstate=(1<<n)-1; 44 for(int i=0; i<=maxstate; i++) 45 { 46 for(int j=0; j<n; j++) 47 { 48 if(i&(1<<j)) 49 continue; 50 if(dp[i]==inf) 51 continue; 52 int tmp=dp[i]+f(val[i],a[j]); 53 if(dp[i|(1<<j)]>tmp) 54 { 55 dp[i|(1<<j)]=tmp; 56 val[i|(1<<j)]=val[i]|a[j]; 57 } 58 } 59 } 60 printf("%d\n",dp[maxstate]); 61 return 0; 62 }