HDU 多校4

开坑站位
题目地址

J. Let Sudoku Rotate

题意:

给你一个16×16的数独盘,你每次可以将一个4×4的数独用方阵顺时针旋转90°,求使得这个数独盘符合规则的最少旋转次数。

题解:

然而模拟爆搜+正确性减枝就好了…
或者你可以用dance-link(dlx)来水…

代码:

然而并没有代码(至死没调出来...)
先放**周振东**dalao写的dlx…

#include <bits/stdc++.h>
#define y0 _zzd01
#define y1 _zzd02
#define hash _zzd03
using namespace std;
const int N=70,M=16+16*16*2+5,S=N*M;
struct DLX{
    int n,m,cnt;
    int x[S],y[S],L[S],R[S],U[S],D[S],cost[N],tot_cost;
    int C[M];
    void init(int c){
        memset(x,0,sizeof x),memset(y,0,sizeof y);
        memset(L,0,sizeof L),memset(R,0,sizeof R);
        memset(U,0,sizeof U),memset(D,0,sizeof D);
        memset(C,0,sizeof C);
        memset(cost,0,sizeof cost);
        m=c,tot_cost=0;
        for (int i=0;i<=m;i++)
            L[i]=i-1,R[i]=i+1,U[i]=D[i]=i;
        L[0]=m,R[m]=0,cnt=m;
    }
    void link(int i,int j){
        cnt++;
        x[cnt]=i;
        y[cnt]=j;
        L[cnt]=cnt-1;
        R[cnt]=cnt+1;
        D[cnt]=j;
        D[U[j]]=cnt;
        U[cnt]=U[j];
        U[j]=cnt;
        C[j]++;
    }
    void Delete(int k){
        L[R[k]]=L[k];
        R[L[k]]=R[k];
        for (int i=D[k];i!=k;i=D[i])
            for (int j=R[i];j!=i;j=R[j]){
                U[D[j]]=U[j];
                D[U[j]]=D[j];
                C[y[j]]--;
            }
    }
    void Reset(int k){
        L[R[k]]=k;
        R[L[k]]=k;
        for (int i=U[k];i!=k;i=U[i])
            for (int j=L[i];j!=i;j=L[j]){
                U[D[j]]=j;
                D[U[j]]=j;
                C[y[j]]++;
            }
    }
    int solve(){
        if (R[0]==0)
            return tot_cost;
        int now=1e9;
        int k=R[0];
        for (int i=R[k];i!=0;i=R[i])
            if (C[i]<C[k])
                k=i;
        Delete(k);
        for (int i=D[k];i!=k;i=D[i]){
            for (int j=R[i];j!=i;j=R[j])
                Delete(y[j]);
            tot_cost+=cost[x[i]];
            now=min(now,solve());
            tot_cost-=cost[x[i]];
            for (int j=L[i];j!=i;j=L[j])
                Reset(y[j]);
        }
        Reset(k);
        return now;
    }
}dlx;
int T,a[20][20],x[N],y[N],z[N];
char s[20];
void swap(int &d,int &c,int &b,int &a){
    int t=a;
    a=b,b=c,c=d,d=t;
}
void Rotate(int x0,int y0){
    int x1=x0+3,y1=y0+3;
    for (int i=0;i<2;i++)
        for (int j=0;j<2;j++)
            swap(a[x0+i][y0+j],a[x0+j][y1-i],a[x1-i][y1-j],a[x1-j][y0+i]);
}
int hash(int f,int i,int j){
    return 16+f*256+(i-1)*16+j;
}
void Debug(){
    for (int i=1;i<=16;i++,puts(""))
        for (int j=1;j<=16;j++)
            printf("%3d",a[i][j]);
    puts("");
}
int main(){
    scanf("%d",&T);
    while (T--){
        scanf("%s",s+1);
        for (int i=1;i<=16;i++){
            for (int j=1;j<=16;j++)
                if ('0'<=s[j]&&s[j]<='9')
                    a[i][j]=s[j]-'0'+1;
                else
                    a[i][j]=s[j]-'A'+11;
            if (i<16)
                scanf("%s",s+1);
        }
        dlx.init(16+16*16*2);
        int Row=0;
        for (int i=1;i<=16;i+=4)
            for (int j=1;j<=16;j+=4)
                for (int k=0;k<4;k++){
                    dlx.cost[++Row]=k;
                    int first=dlx.cnt+1;
                    dlx.link(Row,(i-1)/4*4+(j-1)/4+1);
                    for (int tx=0;tx<4;tx++){
                        int t[4];
                        for (int ty=0;ty<4;ty++)
                            t[ty]=a[i+tx][j+ty];
                        sort(t,t+4);
                        for (int ty=0;ty<4;ty++)
                            dlx.link(Row,hash(0,i+tx,t[ty]));
                    }
                    for (int ty=0;ty<4;ty++){
                        int t[4];
                        for (int tx=0;tx<4;tx++)
                            t[tx]=a[i+tx][j+ty];
                        sort(t,t+4);
                        for (int tx=0;tx<4;tx++)
                            dlx.link(Row,hash(1,j+ty,t[tx]));
                    }
                    dlx.L[first]=dlx.cnt;
                    dlx.R[dlx.cnt]=first;
                    Rotate(i,j);
                }
        printf("%d\n",dlx.solve());
    }
    return 0;
}

L. Graph Theory Homework

题意:

你有n个点,每个点有点权,两点距离为

w[i]w[j] ⌊ w [ i ] − w [ j ] ⌋
1->n的最短路。

题解:

易证得

a+ba+b ⌊ a ⌋ + ⌊ b ⌋ ≥ ⌊ a + b ⌋

官方易证,民间看A题速度…

代码:

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <bits/stdc++.h>
#define P pair<int, int>
#define R register
using namespace std;
const int N = 100500, INF = 0x3f3f3f3f;
int T, n, a[N];
int calc(int i, int j){return floor(sqrt(fabs(1.0 * a[i] - a[j])));}
int main()
{
    scanf("%d", &T);
    for(int _ = 1; _ <= T; _++)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", a + i);
        printf("%d\n", calc(1, n));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值