牛牛的计算机内存(状压DP)

链接:https://ac.nowcoder.com/acm/problem/21873

来源:牛客网

题目描述

牛牛的计算机一共有m块内存,现在有n条指令,每条指令是一个01序列
如果指令的第i个字符为1,说明这条指令需要访问第i块内存
每条指令的执行代价为k^2, k为新访问内存的数量,即之前的指令都没有访问到的内存数量
你可以随意安排n条指令的执行顺序,求执行完所有指令的最小代价

输入描述:

第一行先输入一个整数n (1n201≤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 }

 

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10983535.html