UESTC The Urge to Merge(状态压缩)

来源:互联网 发布:英格蜜儿 知乎 编辑:程序博客网 时间:2024/05/16 15:57

题目大意:给出一个3*n的矩阵,相邻的两个各自可以合并成一个,合并以后的格子的数值是原来两个数值的乘积,每个格子只能合并一次。要求求出这个矩阵每个格子的数值的和最大值。

思路:因为只有三行,把这三行用的状态用三个二进制数表示,dp(i,j)表示到达第j列的时候,这一列状态为i时,可以达到的最大数值。如果i的二进制数第1位为0,说明这一位已经不能合并了,即这个数要么跟前面一列的数合并了,要么跟第j列的数合并了。如果这一位为1,表示这一位可以跟后面的合并,即这一位在目前的状态下不跟任何一个格子合并。对于某一位为0的情况下,首先考虑它跟前面一列合并的情况,然后再考虑它跟本列合并的情况。跟本列合并的只有三种情况,即000,001,100。

代码如下:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int dp[10][1005];int matrix[4][1005];int rec[4];int main(){//freopen("data.txt","r",stdin);ios::sync_with_stdio(false);int n;int kase=0;while(cin>>n){if(n==0)break;matrix[0][0]=0;matrix[1][0]=0;matrix[2][0]=0;matrix[3][0]=0;for(int i=1;i<=3;++i){for(int t=1;t<=n;++t){cin>>matrix[i][t];}}memset(dp,0,sizeof(dp));dp[0][1]=0;dp[1][1]=matrix[2][1]*matrix[3][1];dp[4][1]=matrix[1][1]*matrix[2][1];int tot=1<<3;for(int i=2;i<=n;++i){for(int t=0;t<tot;++t){//0…80‰3i0ˆ40ˆ4¡Á0…70ˆ00…1 for(int j=0;j<tot;++j){//i-1 Linerec[0]=1;rec[1]=0;rec[2]=1;for(int k=0;k<3;++k){if((t&(1<<k))==0)rec[k]=0;else rec[k]=1;}int can=1;int tmp=0;for(int k=0;k<3;++k){if(rec[k]==0&&((j&(1<<k))==0)){can=0;break;}if(rec[k]==1)continue;tmp=tmp+matrix[k+1][i]*matrix[k+1][i-1];}if(!can)continue;dp[t][i]=max(dp[t][i],dp[j][i-1]+tmp);}if(t==0){for(int j=0;j<tot;++j){if(j&(1<<0)){dp[t][i]=max(dp[t][i],dp[j][i-1]+matrix[1][i]*matrix[1][i-1]+matrix[2][i]*matrix[3][i]);}if(j&(1<<2)){dp[t][i]=max(dp[t][i],dp[j][i-1]+matrix[3][i]*matrix[3][i-1]+matrix[1][i]*matrix[2][i]);}}}if(t==1){for(int j=0;j<tot;++j){dp[t][i]=max(dp[t][i],dp[j][i-1]+matrix[3][i]*matrix[2][i]);}}if(t==4){for(int j=0;j<tot;++j){dp[t][i]=max(dp[t][i],dp[j][i-1]+matrix[1][i]*matrix[2][i]);}}}}int ans=0;for(int i=0;i<tot;++i){ans=max(ans,dp[i][n]);}cout<<"Case "<<++kase<<": ";cout<<ans<<endl;}return 0;}


0 0
原创粉丝点击