蓝桥杯ADV-151算法提高花之战的解题思维。
对于100%的数据,我们可以使用状态压缩的方法进行动态规划:
Dp[i][j]的意思是现在I女都参与进来了,占座学生的身份是J的最大系统。
状态j用二进制表示,第k位是1?意味着第k个学生已经被占用了。
比如j=3,二进制数是0000011,说明1和第二个学生已经被占用了。
对于初始状态:
dp[0][j]=0
传递方程为:
DP[I][j]= max(DP[I-1][k]+like[I][t])?
其中t是J中1的1的位置,k是J将第t位变成0的数字。找到所有t的一边取一个最大值然后+like[i][t],就是dp[i][j]?
答案是DP [n] [2 n-1]
时间复杂度应该是o (n * 2 n)
考虑到所有的I只与i-1相关,可以减少一维空间消耗。
对于n
最后,贴一个刚刚写好的新鲜代码:
#包含?& ltiostream & gt
#包含?& ltcstdio & gt
#包含?& ltcstring & gt
#包含?& lt算法& gt
#定义?MAXN?15
使用?命名空间?std
const?int?maxzt =(1 & lt;& lt13);?//最大状态数,
int?DP[maxzt];
int?像[MAXN][MAXN],n;
int?numberOfOne(int?num){?//num?二进制数1。
int?CNT = 0;
while(num){
CNT+=(num & amp;1);
num & gt& gt=1;
}
回归?cnt
}
int?lowbit(int?x){//num?只保留二进制中的最后1?比如:?num=20?二进制10100?回归?二进制100,也就是4。
回归?x & amp(-x);
}
int?posOfOne(int?num){?//num?二进制中最后1的位置如下:?num=18?二进制10010?回归?2
int?pos = 0;
while(num){
pos++;
如果(数字& amp1)
回归?pos
num & gt& gt=1;
}
回归?pos
}
作废?工作(int?x){
int?max status = 1 & lt;& ltn;
for(int?I = 0;我& ltmaxstatusi++){
int?nowstatus=i,t = number of one(now status);
如果(t!=x)?继续;?//x女有x 1。如果没有,继续寻找下一个号码。
while(t - ){
int?pos = low bit(now status);
dp[i]=max(dp[i],DP[I-pos]+like[x][posOfOne(pos)]);
now status-= pos;
}
}
}
int?main(){
scanf("%d ",& ampn);
for(int?I = 1;我& lt= n;i++)
for(int?j = 1;j & lt= n;j++)
scanf("%d ",& amp像[I][j]);
memset(dp,0,sizeof(DP));
for(int?I = 1;我& lt= n;i++)
工作(一);
printf("%d\n ",DP[(1 & lt;& ltn)-1]);
回归?0;
}