CF142C-Help-Caretaker题解
题意:有一个
的矩阵,用尽可能多的“T”形覆盖它(可以旋转),使得它们之间互不重叠。
可以搜索,每次考虑当前位置放哪个角度的“T”形,转移到下一个位置。主要进行最优性剪枝:如果当前填放的数量加上之后的极大值(剩余格子数
最优性剪枝还有另一种形式:记录前
第一种 By cxm1024
#include<bits/stdc++.h>
using namespace std;
int n,m,bst=0;
char now[15][15],ans[15][15];
int dx[4][5]={
{0,-1,-2,-2,-2},
{0,-1,-1,-1,-2},
{0,0,0,-1,-2},
{0,-1,-1,-1,-2}
};
int dy[4][5]={
{-1,-1,0,-1,-2},
{0,0,-1,-2,0},
{0,-1,-2,-1,-1},
{-2,0,-1,-2,-2}
};
void dfs(int x,int y,char ch) {
if(y>m) {
dfs(x+1,3,ch);
return;
}
if(x>n) {
if(ch-'A'>bst) {
bst=ch-'A';
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans[i][j]=now[i][j];
}
return;
}
if(ch-'A'+((n-x+1)*m+(m-y+1))/5<bst) return;
for(int i=0;i<4;i++) {
bool ok=1;
for(int j=0;j<5;j++)
if(now[x+dx[i][j]][y+dy[i][j]]!='.') {
ok=0;
break;
}
if(ok) {
for(int j=0;j<5;j++)
now[x+dx[i][j]][y+dy[i][j]]=ch;
dfs(x,y+1,ch+1);
for(int j=0;j<5;j++)
now[x+dx[i][j]][y+dy[i][j]]='.';
}
}
dfs(x,y+1,ch);
}
signed main() {
cin>>n>>m;
if(n<3||m<3) {
cout<<0<<endl;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++)
cout<<'.';
cout<<endl;
}
return 0;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
now[i][j]='.';
bst=(n/3)*(m/3)-1;
now[1][1]=now[1][2]=now[1][3]=now[2][2]=now[3][2]='A';
dfs(3,4,'B');
now[1][1]=now[1][2]=now[1][3]=now[2][2]=now[3][2]='.';
now[1][1]=now[2][1]=now[3][1]=now[2][2]=now[2][3]='A';
dfs(3,4,'B');
cout<<bst<<endl;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++)
cout<<ans[i][j];
cout<<endl;
}
return 0;
}
第二种代码 By SkyDec
#include<stdio.h>
#include<cstring>
using namespace std;
char ans[15][15];
char t[15][15];int res;
int Max[15];
char shape[5][5][5];
int n,m;
bool check(int x,int y,int type)
{
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(shape[type][i][j]=='j')
if(t[x+i][y+j]!='.')return 0;
return 1;
}
void putshape(int x,int y,int type,int u)
{
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(shape[type][i][j]=='j')
t[x+i][y+j]=u;
}
void dfs(int x,int y,int now)
{
if(x>n)
{
if(now-'A'>=res)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans[i][j]=t[i][j];
res=now-'A';
}
return;
}
int dx=x;int dy=y;dy++;
if(dy>m)dy=1,dx++;
if(now-'A'>Max[x]){Max[x]=now-'A';}
if(now-'A'<Max[x]-3)return;
for(int i=0;i<4;i++)
if(check(x,y,i))
{
putshape(x,y,i,now);
dfs(dx,dy,now+1);
putshape(x,y,i,'.');
}
dfs(dx,dy,now);
}
void init()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
t[i][j]='.';
shape[0][0][0]=shape[0][0][1]=shape[0][0][2]=shape[0][1][1]=shape[0][2][1]='j';
shape[1][2][0]=shape[1][2][1]=shape[1][2][2]=shape[1][0][1]=shape[1][1][1]='j';
shape[2][0][2]=shape[2][1][2]=shape[2][2][2]=shape[2][1][0]=shape[2][1][1]='j';
shape[3][0][0]=shape[3][1][0]=shape[3][2][0]=shape[3][1][1]=shape[3][1][2]='j';
}
int main()
{
scanf("%d%d",&n,&m);
init();
dfs(1,1,'A');
printf("%d\n",res);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)putchar(ans[i][j]);
putchar('\n');
}
return 0;
}
DFS 可以使用也状压的记忆化来加速。当然也可以直接使用状压 DP。设
By rng_58
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define two(a,b,c,d) ((1<<(a))|(1<<(b))|(1<<(c))|(1<<(d)))
int dp[10][10][(1<<19)];
char ans[10][10];
int main(void){
int X,Y,i,j,mask;
cin >> X >> Y;
int A = two(0,1,Y,2*Y);
int B = two(Y-3,Y-2,Y-1,2*Y-1);
int C = two(Y-1,2*Y-2,2*Y-1,2*Y);
int D = two(Y-1,Y,Y+1,2*Y-1);
int T = (1<<(2*Y+1));
for(i=X-1;i>=0;i--) for(j=Y-1;j>=0;j--){
int i2 = i, j2 = j+1;
if(j2 == Y) {i2++; j2 = 0;}
REP(mask,T){
int mask2 = mask/2;
dp[i][j][mask] = max(dp[i][j][mask], dp[i2][j2][mask2]);
if(!(mask&1)){
if(!(mask2&A) && i+2 < X && j+2 < Y) dp[i][j][mask] = max(dp[i][j][mask], dp[i2][j2][mask2|A] + 1);
if(!(mask2&B) && i+2 < X && j-2 >= 0) dp[i][j][mask] = max(dp[i][j][mask], dp[i2][j2][mask2|B] + 1);
if(!(mask2&C) && i+2 < X && j-1 >= 0 && j+1 < Y) dp[i][j][mask] = max(dp[i][j][mask], dp[i2][j2][mask2|C] + 1);
if(!(mask2&D) && i+2 < X && j+2 < Y) dp[i][j][mask] = max(dp[i][j][mask], dp[i2][j2][mask2|D] + 1);
}
}
}
cout << dp[0][0][0] << endl;
REP(i,X) REP(j,Y) ans[i][j] = '.';
i = 0; j = 0; mask = 0;
char ch = 'A';
while(dp[i][j][mask] > 0){
int i2 = i, j2 = j+1;
if(j2 == Y) {i2++; j2 = 0;}
int mask2 = mask/2;
if(dp[i][j][mask] == dp[i2][j2][mask2]){
i = i2; j = j2; mask = mask2;
continue;
}
if(!(mask2&A) && i+2 < X && j+2 < Y && dp[i][j][mask] == dp[i2][j2][mask2|A] + 1){
ans[i][j] = ans[i][j+1] = ans[i][j+2] = ans[i+1][j+1] = ans[i+2][j+1] = ch;
i = i2; j = j2; mask = (mask2 | A); ch++;
continue;
}
if(!(mask2&B) && i+2 < X && j-2 >= 0 && dp[i][j][mask] == dp[i2][j2][mask2|B] + 1){
ans[i][j] = ans[i+1][j-2] = ans[i+1][j-1] = ans[i+1][j] = ans[i+2][j] = ch;
i = i2; j = j2; mask = (mask2 | B); ch++;
continue;
}
if(!(mask2&C) && i+2 < X && j-1 >= 0 && j+1 < Y && dp[i][j][mask] == dp[i2][j2][mask2|C] + 1){
ans[i][j] = ans[i+1][j] = ans[i+2][j-1] = ans[i+2][j] = ans[i+2][j+1] = ch;
i = i2; j = j2; mask = (mask2 | C); ch++;
continue;
}
if(!(mask2&D) && i+2 < X && j+2 < Y && dp[i][j][mask] == dp[i2][j2][mask2|D] + 1){
ans[i][j] = ans[i+1][j] = ans[i+1][j+1] = ans[i+1][j+2] = ans[i+2][j] = ch;
i = i2; j = j2; mask = (mask2 | D); ch++;
continue;
}
}
REP(i,X){
REP(j,Y) cout << ans[i][j];
cout << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步