zoukankan      html  css  js  c++  java
  • [TJOI2015]线性代数 题解

    [TJOI2015]线性代数 题解

    Problem

    ​ 为了提高智商,ZJY 开始学习线性代数。

    ​ 她的小伙伴菠萝给她出了这样一个问题:给定一个(n imes n)的矩阵(B)和一个(1 imes n)的矩阵(C)。求出一个(1 imes n)的01矩阵(A),使得(D=(A imes B -C) imes A^{T})最大,输出(D)(1 leq n leq 500))。

    Solution

    ​ 正解是网络流......这篇题解只是提供一个乱搞方法。

    ​ 这题乍一看是线性代数,感觉推式子暴力化表达式会很麻烦,似乎不可做的样子。

    ​ 但是,发现(n)的范围很小,再加之(A)(1 imes n)的01矩阵,于是情况便变得简单起来,我们可以尝试随机一个(A),再暴力算出(D),更新答案,每一次的复杂度是(O(n^2))的,大概能随机将近1000次,正确率还是比较高的。

    ​ 还有一个要注意的地方,(A)矩阵初始化应该是全1,因为要使(D)最大,这样概率会大很多,两种初始化方法得分简直天壤之别......

    Code

    #include<bits/stdc++.h>
    #define eps 1e-8
    using namespace std;
    int n;
    
    struct Matrix{
    
        int C,L;
        
        int M[505][505];
    
        Matrix(){
            C=L=0;
            memset(M,0,sizeof M);
        }
    
        friend Matrix operator - (Matrix A,Matrix B){
            Matrix res;
            res.C=A.C;res.L=B.L;
            for(register int i=1;i<=A.C;++i)
            for(register int j=1;j<=B.L;++j)
                res.M[i][j]=A.M[i][j]-B.M[i][j];
            return res;
        }
    
        friend Matrix operator * (Matrix A,Matrix B){
            Matrix res;
            res.C=A.C;res.L=B.L;
            for(register int i=1;i<=A.C;++i)
            for(register int k=1;k<=A.L;++k)
            for(register int j=1;j<=B.L;++j)
                res.M[i][j]+=A.M[i][k]*B.M[k][j];
            return res;
        }
    
    }A,B,C,Ans;    
    
    Matrix Trans(Matrix A){
        Matrix res;
        res.C=A.L;res.L=A.C;
        for(register int i=1;i<=A.C;++i)
        for(register int j=1;j<=A.L;++j)
            res.M[j][i]=A.M[i][j];
        return res;
    } 
    
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){
           if(ch=='-')f=-1;
           ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
           x=(x<<1)+(x<<3)+ch-'0';
           ch=getchar();
        }
        return x*f;
    }
    
    void Simulate_Anneal(){
        Matrix Res=A;
        double T=2000,d=0.998;
        while(T>eps&&1.0*clock()/CLOCKS_PER_SEC<0.8){
            Matrix Now=Res;
            Now.M[1][rand()%n+1]^=1;
            Matrix Sum=(Now*B-C)*Trans(Now);
            if(Sum.M[1][1]>Ans.M[1][1]){
                A=Res=Now;
                Ans.M[1][1]=Sum.M[1][1];
            }
            else if(exp((Sum.M[1][1]-Ans.M[1][1])/T)>1.0*rand()/RAND_MAX)
                Res=Now;
            T*=d;
        }
        return;
    }
    
    int main(){
    
        n=read();
    
        B.C=n;B.L=n;
        for(register int i=1;i<=n;++i)
        for(register int j=1;j<=n;++j)
            B.M[i][j]=read();
    
        C.C=1;C.L=n;
        for(register int i=1;i<=n;++i)
            C.M[1][i]=read();
    
        A.C=1;A.L=n;
        for(register int i=1;i<=n;++i)
            A.M[1][i]=1;
    
        Ans=(A*B-C)*Trans(A);
    	
    	srand(time(0));
        while(1.0*clock()/CLOCKS_PER_SEC<0.8)
            Simulate_Anneal();
    
        printf("%d
    ",Ans.M[1][1]);
    
        return 0;
    }
    
  • 相关阅读:
    C++ 运行时类型识别 知道实例父类类型,显示出子类类型
    C++里面方便的打印日志到文件
    vs2015上配置Armadillo+openBlas
    opencl 在vs2015上遇见的问题
    Lucene子项目------------------Solr遇到的问题
    [LeetCode]Course Schedule
    [LeetCode]Minimum Size Subarray Sum
    [LeetCode]Reverse Linked List
    [LeetCode]Isomorphic Strings
    [LeetCode]Ugly Number
  • 原文地址:https://www.cnblogs.com/zjy123456/p/13714838.html
Copyright © 2011-2022 走看看