hdu 4592 Boring Game

来源:互联网 发布:mac怎么调整图片方向 编辑:程序博客网 时间:2024/06/01 09:51

Boring Game

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 544    Accepted Submission(s): 91


Problem Description
Zero likes to play a boring game when he feels extremely boring. This his game proceeds in a square board with n rows and n column. Each grid in the board has either of two colors black or white. In each turn, Zero chooses a grid first. Let’s assume that the grid he chooses locates in the xth row and the yth column. And then, the neighbors which are existed of this grid (x + 1, y), (x – 1, y), (x, y + 1), (x, y – 1) and itself will convert their color into another. Till the end, Zero will transform the initial board to the goal board whose grids are all white. For instance, Here is the way to attain his goal. In his first turn, he selects (2, 2). And then he selects (1, 1) in the second turn. After that, he reaches his goal.

Zero reckons this mission, however, is too simple and naive. So he prefers to accomplish this assignment in minimal turns. He doesn’t know whether the turns he needs are the minimal turns, because of that he needs you to tell him the minimal turns of these initial boards.
 

Input
There are several test cases in the input file. The first line of the input file contains an integer m(m <= 106), then m cases follow.
The first line of each test case contains an integer n(1 <= n <= 8), which is the length of a side of the square board.
Then the next line contains n integer a[i](0 <= a[i] <= 2n, 1 <= i <= n), which is the statement of the ith row respectively. The definition of a statement can be illustrated as n-length binary numbers, zero represents white and one represents black. For example, when n is equal to 4 and a[0] is equal to 5 = (0101)2, you can consider that the condition in the first line of this board is white, black, white, black.
 

Output
For each test case, output the minimal turns. If the initial board doesn’t contain a way to reach the goal board, please output -1.
 

Sample Input
234 3 241 0 0 0
 

Sample Output
2-1
 

Source
2013 ACM-ICPC南京赛区全国邀请赛——题目重现
 



题解及代码:


      这道题的意思很简单,但是数据量巨大,而且卡时间卡的比较紧,这样我们可以进行一下预处理。我们将n=1---8高消之后的矩阵求出来可以看到:4和5是多解的情况,而其他的都是唯一解。那么我们就可以把其他情况的系数矩阵的逆矩阵求出来,直接打表放在代码中,当我们输入增广矩阵的最后一列的时候,就直接与逆矩阵直接相乘就能得到最后结果;对于4和5,我们就直接用高消求就可以了。

      按照这种方法,只能运行到将近95W组数据,所以还需要处理一下:我们已经将逆矩阵求出来了,每一位不是0就是1,整个矩阵还是比较大,枚举的话还是会超时,所以我们将每n位换算成一个10进制数,矩阵相乘时,直接异或就可以了,最后求一下每个x[i]中1的个数就可以了,这样能节省很多时间。

      看了看ac的名单,感觉这思路还不是很好,代码量巨大,而且速度也不快,如果读者有更好的方法,希望能留言,探讨一下这道题,感谢!

time:2953ms


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;int A2[4][2]={    {3,2},{3,1},    {2,3},{1,3}};int A3[9][3]={    {5,1,6},{0,2,7},{5,4,3},    {1,3,1},{2,7,2},{4,6,4},    {6,1,5},{7,2,0},{3,4,5}};int A6[36][6]={    {43,8,55,10,44,40},{3,20,53,17,14,4},{44,42,7,32,55,34},{13,21,56,1,59,17},{48,10,43,34,28,8},{53,4,59,20,13,5},    {8,28,2,27,34,44},{20,54,5,59,21,14},{42,43,10,48,2,55},{21,53,20,3,16,59},{10,27,40,55,42,28},{4,14,16,54,17,13},    {55,2,48,42,27,10},{53,5,56,1,59,17},{7,10,28,40,48,32},{56,20,14,5,3,1},{43,40,7,32,55,34},{59,16,3,21,54,20},    {10,27,42,48,2,55},{17,59,1,56,5,53},{32,48,40,28,10,7},{1,3,5,14,20,56},{34,55,32,7,40,43},{20,54,21,3,16,59},    {44,34,27,2,28,8},{14,21,59,5,54,20},{55,2,48,10,43,42},{59,16,3,20,53,21},{28,42,55,40,27,10},{13,17,54,16,14,4},    {40,44,10,55,8,43},{4,14,17,53,20,3},{34,55,32,7,42,44},{17,59,1,56,21,13},{8,28,34,43,10,48},{5,13,20,59,4,53}};int A7[49][7]={    {109,65,14,84,88,16,96},{108,34,27,2,28,40,112},{3,20,53,81,110,84,56},{107,0,107,8,119,42,28},{96,20,86,69,59,21,14},    {27,34,108,32,28,10,7},{91,65,56,21,13,4,3},{65,99,21,86,68,56,16},{34,119,32,7,42,108,40},{20,54,69,91,5,86,84},    {0,0,8,28,34,107,42},{20,54,81,109,80,53,21},{34,119,2,112,42,27,10},{65,99,84,53,17,14,4},{14,21,59,5,54,68,88},    {27,32,107,8,119,42,28},{53,69,88,17,99,5,110},{107,8,119,34,0,34,119},{86,81,13,68,99,80,59},{108,2,107,8,119,42,28},    {56,84,110,80,54,17,13},{84,86,5,91,5,86,84},{2,7,8,27,8,7,2},{81,91,17,96,17,91,81},{8,28,34,107,34,28,8},    {69,109,68,3,68,109,69},{32,112,8,108,8,112,32},{21,53,80,109,80,53,21},{88,68,54,5,59,21,14},{28,42,119,8,107,32,27},    {110,5,99,17,88,69,53},{119,34,0,34,119,8,107},{59,80,99,68,13,81,86},{28,42,119,8,107,2,108},{13,17,54,80,110,84,56},    {16,56,68,86,21,99,65},{40,108,42,7,32,119,34},{84,86,5,91,69,54,20},{42,107,34,28,8,0,0},{21,53,80,109,81,54,20},    {10,27,42,112,2,119,34},{4,14,17,53,84,99,65},{96,16,88,84,14,65,109},{112,40,28,2,27,34,108},{56,84,110,81,53,20,3},    {28,42,119,8,107,0,107},{14,21,59,69,86,20,96},{7,10,28,32,108,34,27},{3,4,13,21,56,65,91}};int A8[64][8]={    {220,138,7,128,199,170,108,40},{214,81,13,64,237,1,238,68},{27,0,27,32,107,168,199,130},{237,81,54,16,14,5,3,1},    {183,138,108,8,112,160,192,128},{216,0,216,4,214,21,227,65},{107,138,176,2,183,128,119,34},{59,81,224,1,227,85,54,20},    {138,219,10,192,42,171,130,108},{81,219,17,224,65,3,69,238},{0,0,32,112,136,172,42,199},{81,219,65,56,21,13,4,3},    {138,219,130,28,168,176,32,192},{0,0,4,14,17,53,84,227},{138,219,136,7,130,192,162,119},{81,219,80,3,84,213,65,54},    {7,10,28,160,172,2,171,170},{13,17,54,16,14,5,3,1},{27,32,107,136,183,10,172,168},{54,65,213,68,59,20,13,5},    {108,130,171,34,220,40,176,160},{216,4,214,17,237,80,53,21},{176,136,108,8,112,160,192,128},{224,80,56,5,53,64,213,85},    {128,192,160,112,136,172,42,199},{64,224,16,216,84,14,65,237},{32,112,136,172,10,183,136,107},{16,56,68,214,69,59,21,14},    {8,28,34,107,162,220,168,112},{4,14,17,53,80,237,17,214},{2,7,8,27,42,112,130,183},{1,3,5,14,17,53,84,227},    {199,42,172,136,112,160,192,128},{237,65,14,84,216,16,224,64},{107,136,183,10,172,136,112,32},{14,21,59,69,214,68,56,16},    {112,168,220,162,107,34,28,8},{214,17,237,80,53,17,14,4},{183,130,112,42,27,8,7,2},{227,84,53,17,14,5,3,1},    {170,171,2,172,160,28,10,7},{1,3,5,14,16,54,17,13},{168,172,10,183,136,107,32,27},{5,13,20,59,68,213,65,54},    {160,176,40,220,34,171,130,108},{21,53,80,237,17,214,4,216},{128,192,160,112,8,108,136,176},{85,213,64,53,5,56,80,224},    {108,130,171,42,192,10,219,138},{238,69,3,65,224,17,219,81},{199,42,172,136,112,32,0,0},{3,4,13,21,56,65,219,81},    {192,32,176,168,28,130,219,138},{227,84,53,17,14,4,0,0},{119,162,192,130,7,136,219,138},{54,65,213,84,3,80,219,81},    {40,108,170,199,128,7,138,220},{68,238,1,237,64,13,81,214},{130,199,168,107,32,27,0,27},{1,3,5,14,16,54,81,237},    {128,192,160,112,8,108,138,183},{65,227,21,214,4,216,0,216},{34,119,128,183,2,176,138,107},{20,54,85,227,1,224,81,59}};int a[30][30],x[80];//系数矩阵,解数组int equ,var;//方程数,变元数int Gauss(){    int k,col,max_r;    for(k=0,col=0; k<equ&&col<var; k++,col++)    {        if(a[k][col]==0)        {            max_r=k;            for(int i=k+1; i<equ; i++)                if(a[i][col]>a[max_r][col])                {                    max_r=i;                    break;                }            if(max_r!=k)                for(int i=0; i<=var; i++)                    swap(a[max_r][i],a[k][i]);        }        if(a[k][col]==0)        {            k--;            continue;        }        for(int i=k+1; i<equ; i++)        {            if(a[i][col])                for(int j=col; j<=var; j++)                    a[i][j]=a[i][j]^a[k][j];        }    }    for(int i=k; i<equ; i++)        if(a[i][var]) return -1;    int lim=(1<<(var-k)),ans=100000;    for(int i=0; i<lim; i++)    {        int temp=i,sum=0;        for(int j=var-1; j>=k; j--)        {            x[j]=temp&1;            temp>>=1;        }        for(int j=k-1; j>=0; j--)        {            x[j]=a[j][var]&1;            for(int r=j+1; r<var; r++)                x[j]=x[j]^(a[j][r]&x[r]);        }        for(int j=0; j<var; j++)            sum+=x[j];        ans=min(ans,sum);    }    return ans;}void init(int n){    equ=n*n;    var=equ;    memset(a,0,sizeof(a));    memset(x,0,sizeof(x[0])*30);    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            if(i!=0) a[i*n+j][(i-1)*n+j]=1;            if(i!=n-1) a[i*n+j][(i+1)*n+j]=1;            if(j!=0) a[i*n+j][i*n+j-1]=1;            if(j!=n-1) a[i*n+j][i*n+j+1]=1;            a[i*n+j][i*n+j]=1;        }}int main(){    int cas,n,X;    scanf("%d",&cas);    while(cas--)    {        scanf("%d",&n);        if(n==1)        {            scanf("%d",&X);            printf("%d\n",X);            continue;        }        if(n==4||n==5)        {            init(n);            for(int i=0; i<n; i++)            {                scanf("%d",&X);                int r=(i+1)*n-1,l=i*n;                while(r>=l)                {                    a[r][var]=X&1;                    X>>=1;                    r--;                }            }            int ans=Gauss();            printf("%d\n",ans);            continue;        }        int ans=0;        int t[80];        for(int i=0; i<n; i++)        {            scanf("%d",&t[i]);        }        equ=n*n;        memset(x,0,sizeof(x[0])*(equ+4));        if(n==2)        {            for(int j=0; j<n; j++)                if(t[j])                {                    for(int i=0; i<equ; i++)                    {                        x[i]=x[i]^(A2[i][j]&t[j]);                    }                }        }        else if(n==3)        {            for(int j=0; j<n; j++)                if(t[j])                {                    for(int i=0; i<equ; i++)                    {                        x[i]=x[i]^(A3[i][j]&t[j]);                    }                }        }        else if(n==6)        {            for(int j=0; j<n; j++)                if(t[j])                {                    for(int i=0; i<equ; i++)                    {                        x[i]=x[i]^(A6[i][j]&t[j]);                    }                }        }        else if(n==7)        {            for(int j=0; j<n; j++)                if(t[j])                {                    for(int i=0; i<equ; i++)                    {                        x[i]=x[i]^(A7[i][j]&t[j]);                    }                }        }        else if(n==8)        {            for(int j=0; j<n; j++)                if(t[j])                {                    for(int i=0; i<equ; i++)                    {                        x[i]=x[i]^(A8[i][j]&t[j]);                    }                }        }        for(int i=0; i<equ; i++)        {            int t=0;            while(x[i])            {                t^=(x[i]&1);                x[i]>>=1;            }            ans+=t;        }        printf("%d\n",ans);    }    return 0;}


优化:今天,在老师的指导下,又进行了优化:在最开始的基础上,我们把打出来的二进制的逆矩阵的表的每一行用一个10进制来表示,而不是上面的所说的用n个十进制数表示,这样,我们把输入的增光矩阵的那一列的每个数字,转换成二进制,这样我们就能知道在进行矩阵乘法的时候,哪一行的数字进行了乘法(参照矩阵乘法的优化),我们把这些行挑出来,直接进行异或,异或之后的结果,在计算其二进制下有多少个1就行了。

time:1953ms


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;unsigned __int64 A2[4]={14,13,11,7};unsigned __int64 A3[9]={334,23,355,89,186,308,397,464,229};unsigned __int64 A6[36]={46319577896,3570733956,47951252962,14325653201,51718792968,56990974789,9060333740,22382359886,45821395127,23443027003,11201116828,4534264909,59102111434,57006890705,7691471904,60468777153,46843956706,63620078996,11201609911,19243958645,35175645831,1125442872,37438388779,22386324539,47822153480,15400197524,59101981418,63620074837,30783997642,14258078596,43690717739,4534523139,37438388908,19243959629,9068786352,5592297781};unsigned __int64 A7[49]={481624388405344,476164506719344,13895733062200,470619718014236,422922890955406,119944545502471,402470692143619,289280455941136,153630995559976,89835069074260,2206774698,89838329272981,153623162686858,289297297327876,62310054732376,119875508753692,235490946630382,470897869721975,381018772662331,475086484002076,249206519203981,372392377543508,9038815429506,359373268610513,36155796524552,307228681778885,144588153174048,94201747610261,389379062155918,124620373676059,483983527125685,524535839179883,262260241164502,124620373672300,57773385296440,72311323849153,179644001696674,372392378587924,188403631128576,94201747626772,44919687265186,18077898322369,422786019598573,493963119612268,249206521285123,124620373672043,62310189468256,31137508036891,13335113113819};unsigned __int64 A8[64]={15891522484817259560,15443139169735536196,1945584865083180930,17100508702685070081,13225502039232004224,15564677827475661633,7749199634559432482,4274443820064912916,10005602817599570540,5898327791832876526,35667701410503,5898379846098945027,10005734056734499008,4458464761059,10005740562973500023,5898396112210182454,507249384438803370,941593239679730433,1954680473209449640,3909640440559963397,7819000069279494304,15565801584583521557,12720535931013087360,16163480657652143445,9277591637572987591,4674754934519775725,2337518479100840043,1168759790377833742,584379897340536944,292189946514313686,146094425681986231,72907576944448739,14351472864574619776,17095961418040139840,7748644415363117088,1014782462175492112,8117980918475529224,15425371127464136196,13223254782057645826,16380776092019262209,12297926147909093895,72907576927719693,12154101277750140955,363969389677330742,11578799567909126764,1528216627698861272,9277591635421333680,6184920259728265440,7819000103167515530,17169132735886908241,14351472864566181888,217313066809940817,13844259490616236938,16380776092019195904,8620664301445241738,3909640508343901009,2912890832825060060,4966909557529727446,9423685923349659675,72907576927736301,9277591635421334199,4747662441127084248,2483595243030612587,1456445962978349371};int a[30][30],x[80];int equ,var;int Gauss(){    int k,col,max_r;    for(k=0,col=0; k<equ&&col<var; k++,col++)    {        if(a[k][col]==0)        {            max_r=k;            for(int i=k+1; i<equ; i++)                if(a[i][col]>a[max_r][col])                {                    max_r=i;                    break;                }            if(max_r!=k)                for(int i=0; i<=var; i++)                    swap(a[max_r][i],a[k][i]);        }        if(a[k][col]==0)        {            k--;            continue;        }        for(int i=k+1; i<equ; i++)        {            if(a[i][col])                for(int j=col; j<=var; j++)                    a[i][j]=a[i][j]^a[k][j];        }    }    for(int i=k; i<equ; i++)        if(a[i][var]) return -1;    int lim=(1<<(var-k)),ans=100000;    for(int i=0; i<lim; i++)    {        int temp=i,sum=0;        for(int j=var-1; j>=k; j--)        {            x[j]=temp&1;            temp>>=1;        }        for(int j=k-1; j>=0; j--)        {            x[j]=a[j][var]&1;            for(int r=j+1; r<var; r++)                x[j]=x[j]^(a[j][r]&x[r]);        }        for(int j=0; j<var; j++)            sum+=x[j];        ans=min(ans,sum);    }    return ans;}void init(int n){    equ=n*n;    var=equ;    memset(a,0,sizeof(a));    memset(x,0,sizeof(x[0])*30);    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            if(i!=0) a[i*n+j][(i-1)*n+j]=1;            if(i!=n-1) a[i*n+j][(i+1)*n+j]=1;            if(j!=0) a[i*n+j][i*n+j-1]=1;            if(j!=n-1) a[i*n+j][i*n+j+1]=1;            a[i*n+j][i*n+j]=1;        }}int main(){    int cas,n,X;    scanf("%d",&cas);    while(cas--)    {        scanf("%d",&n);        if(n==1)        {            scanf("%d",&X);            printf("%d\n",X);            continue;        }        if(n==4||n==5)        {            init(n);            for(int i=0; i<n; i++)            {                scanf("%d",&X);                int r=(i+1)*n-1,l=i*n;                while(r>=l)                {                    a[r][var]=X&1;                    X>>=1;                    r--;                }            }            int ans=Gauss();            printf("%d\n",ans);            continue;        }        unsigned __int64 ans=0;        int t[80],k=0;        for(int i=0; i<n; i++)        {            scanf("%d",&X);            int r=(i+1)*n-1,l=i*n;            while(r>=l)            {                if(X&1)                 t[k++]=r;                X>>=1;                r--;            }        }        if(n==2)        {            for(int i=0;i<k;i++)                ans^=A2[t[i]];        }        else if(n==3)        {            for(int i=0;i<k;i++)                ans^=A3[t[i]];        }        else if(n==6)        {            for(int i=0;i<k;i++)                ans^=A6[t[i]];        }        else if(n==7)        {            for(int i=0;i<k;i++)                ans^=A7[t[i]];        }        else if(n==8)        {            for(int i=0;i<k;i++)                ans^=A8[t[i]];        }        unsigned __int64 sum=0;        while(ans)        {            sum+=(ans&1);            ans>>=1;        }        printf("%I64d\n",sum);    }    return 0;}






0 0
原创粉丝点击