Vijos2034

这是极大极小值算法原理,不断递归

alpha_bata算法是对其的一个优化

当当前这轮选的是答案尽量大的值时(pro_max),到(pro_min)里搜索时,去的是尽量小的值,若当前能取到比在pro_max平行的前几轮里更小的,则pro_max里即可避免掉这种方案,取前几种方案
pro_min同理

//开了rigister 后快了0.7s 
#include<cstdio>
#include<cctype>
#include<algorithm>
#define INF 1000000007
using namespace std;
int a[4][4],k,sum,tot;
inline void read(int &x){
    char ch=getchar();x=0;int f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    x*=f;
}
void ratal(int x,int y){
    int tmp=a[x][y];
    a[x][y]=a[x][y+1];
    a[x][y+1]=a[x+1][y+1];
    a[x+1][y+1]=a[x+1][y];
    a[x+1][y]=tmp;
    sum+=a[x][y]+a[x+1][y]+a[x][y+1]+a[x+1][y+1];
}
void ratar(int x,int y){
    int tmp=a[x][y];
    a[x][y]=a[x+1][y];
    a[x+1][y]=a[x+1][y+1];
    a[x+1][y+1]=a[x][y+1];
    a[x][y+1]=tmp;
    sum-=(a[x][y]+a[x+1][y]+a[x][y+1]+a[x+1][y+1]);
}
int pro_max(int dep,int alph,int bet);
int pro_min(int dep,int alph,int bet);

int pro_max(int dep,int alph,int bet){
    if(dep==k)return sum;
    pair<int,int>f[9];
    for(register int i=0;i<3;i++)
       for(register int j=0;j<3;j++){
           f[i*3+j]=make_pair(a[i][j]+a[i][j+1]+a[i+1][j]+a[i+1][j+1],i*3+j);
       }
    sort(f,f+9);
    for(register int i=8;i>=0;i--){
        int x=f[i].second/3,y=f[i].second%3;
        ratal(x,y);
        int val=pro_min(dep+1,alph,bet);
        ratar(x,y);
        if(val>=bet)return bet;
        if(val>alph)alph=val;
    }
    return alph;
}

int pro_min(int dep,int alph,int bet){
    if(dep==k)return sum;
    pair<int,int>f[9];
    for(register int i=0;i<3;i++)
       for(register int j=0;j<3;j++){
           f[i*3+j]=make_pair(a[i][j]+a[i][j+1]+a[i+1][j]+a[i+1][j+1],i*3+j);
       }
    sort(f,f+9);
    for(register int i=0;i<=8;i++){
        int x=f[i].second/3,y=f[i].second%3;
        ratal(x,y);
        int val=pro_max(dep+1,alph,bet);
        ratar(x,y);
        if(val<=alph)return alph;
        if(val<bet)bet=val;
    }
    return bet;
}

int main(){
    int T;
    read(T);
    while(T--){
        read(k);k*=2;
        for(register int i=0;i<4;i++)for(register int j=0;j<4;j++)read(a[i][j]);
        printf("%d\n",pro_max(0,0,INF));
    }
}

 

posted @ 2018-05-11 20:56  lnyzo  阅读(104)  评论(0编辑  收藏  举报