題目鏈接:https://ac.nowcoder.com/acm/contest/886/G
思路:根據題意直接模擬計算,從進行暴搜回溯且此時的條件下是否滿足,直到找到滿足條件的情況,用蔡勒公式來判斷是否是星期五就了,讀入時不去重會超時!
AC代碼:
#include<bits/stdc++.h>
using namespace std;
int n;
int flag=0;
int vis[13];
int tmp[13];
char a[100010][13];
int datatoint(int m,int d,int y)//蔡勒公式
{
return 1461*(y+4800+(m-14)/12)/4
+367*(m-2-(m-14)/12*12)/12
-3*((y+4900+(m-14)/12)/100)/4
+d-32075;
}
int check()
{
for(int i=0;i<n;i++){
int y=0,m=0,d=0;
for(int j=0;j<=3;j++){
y=y*10+tmp[a[i][j]-'A'];
}
for(int j=5;j<=6;j++){
m=m*10+tmp[a[i][j]-'A'];
}
for(int j=8;j<=9;j++){
d=d*10+tmp[a[i][j]-'A'];
}
if(y<1600||m>12||d>31){
return 0;
}
if((m==4||m==6||m==9||m==11)&&d>30){
return 0;
}
int c=28;
if(y%400==0||(y%4==0&&y%100!=0)){
c+=1;
}
if(m==2&&d>c){
return 0;
}
int tm=datatoint(m,d,y)+1;
//cout<<tm%7<<endl;
if(tm%7!=5){//判斷不是週五
return 0;
}
}
return 1;
}
void dfs(int d)
{
if(d>=10){
flag=check();
return ;
}
for(int i=0;i<10;i++){
if(!vis[i]){
vis[i]=1;
tmp[d]=i;
dfs(d+1);
vis[i]=0;//暴搜回溯
if(flag){
return ;
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
for(int k=1;k<=t;k++){
for(int i=0;i<10;i++){
vis[i]=0;
tmp[i]=0;
}
flag=0;
scanf("%d\n",&n);
for(int i=0;i<n;i++){
scanf("%s",&a[i]);
if(i>0&&strcmp(a[i],a[i-1])==0){//不去重會超時
i--;
n--;
}
}
dfs(0);//從0開始暴搜
printf("Case #%d: ",k);
if(flag){
for(int i=0;i<10;i++){
printf("%d",tmp[i]);
}
printf("\n");
}
else {
printf("Impossible\n");
}
}
return 0;
}