开坑站位
题目地址
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−−√⌋+⌊b√⌋≥⌊a+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));
}
}