• [GDOI2014]拯救莫莉斯


    XXXV.[GDOI2014]拯救莫莉斯

    因为\(nm\leq 50,m\leq n\)

    所以\(m\)最大只会到\(7\),可以状压。

    考虑设\(f[i][j][k]\)表示:

    在前\(i-1\)行已经填好的情况下,第\(i-1\)行状态为\(j\),第\(i\)行状态为\(k\)的最小代价和最小数量(是个std::pair)。

    转移时枚举\(i-2\)行的状态。复杂度\(O(n2^{3m})\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define bp __builtin_popcount
    #define pii pair<int,int>
    #define x first
    #define y second
    #define mp make_pair
    int n,m,c[100][100],lim,s[100][1<<8];
    pii f[100][1<<8][1<<8],res=mp(0x3f3f3f3f,0x3f3f3f3f);
    pii operator+(const pii &u,const pii &v){
    	return mp(u.x+v.x,u.y+v.y);
    }
    bool che(int i,int j,int k){
    	int jj=j;
    	jj|=(j>>1)&(lim-1);
    	jj|=(j<<1)&(lim-1);
    	jj|=i;
    	jj|=k;
    	return jj==(lim-1);
    }
    int main(){
    	scanf("%d%d",&n,&m),memset(f,0x3f3f3f3f,sizeof(f)),lim=(1<<m);
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++)scanf("%d",&c[i][j]);
    		for(int j=0;j<lim;j++)for(int k=0;k<m;k++)if(j&(1<<k))s[i][j]+=c[i][k];
    	}
    	if(n==1){printf("%d %d\n",1,c[0][0]);return 0;}
    	for(int i=0;i<lim;i++)for(int j=0;j<lim;j++)if(che(0,i,j))f[1][i][j]=make_pair(s[0][i]+s[1][j],bp(i)+bp(j));
    	for(int i=2;i<n;i++)for(int j=0;j<lim;j++)for(int k=0;k<lim;k++)for(int l=0;l<lim;l++)if(che(l,j,k))f[i][j][k]=min(f[i][j][k],f[i-1][l][j]+mp(s[i][k],bp(k)));
    	for(int i=0;i<lim;i++)for(int j=0;j<lim;j++)if(che(0,j,i))res=min(res,f[n-1][i][j]);
    	printf("%d %d\n",res.y,res.x);
    	return 0;
    }
    

  • 相关阅读:
    作业 第四 张垚
    软件测试课堂练习 张垚
    增删改查
    计算器 作业
    activity 张垚
    第四作业 张垚
    第六周作业
    jsp第四周作业
    jsp求1-100之间的素数和
    JSP第一次测试
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597165.html
Copyright © 2020-2023  润新知