云斗杯 · 五月 Silver 组模拟赛T1T2题解
为啥只有T1和T2? 因为T3T4不会
T1:无所谓的第一道题
题意:给定一张
X 定义为用
例如:
101 010 101
中有一个X;
1001 0110 0110 1001
中有两个斜线长度为4的X。
————————↑以上内容均为题目描述↑—————————
考虑如何做:对于中心点为
那么对于中心为一个块的怎么处理呢?
可以回想一下我们学manachar的时候,是在字符串中插入一些相同的占位符号,以保证每次都能找到一个对称中心。这道题我们也可以用相同的思路处理。也就是,在每一行和每一列之间插入一个字符,然后枚举中心点即可。
复杂度:
当然,可以优化的点很多。
代码:
#include<bits/stdc++.h> using namespace std; const int N = 205; char a[N][N], s[N][N]; int n; int dx[4] = {-1, 1, -1, 1}; int dy[4] = {-1, 1, 1, -1}; int X[4], Y[4]; int main() { scanf("%d", &n); for(int i = 1; i<=n; i++) { scanf("%s", a[i]+1); } for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { s[(i<<1)-1][(j<<1)-1] = a[i][j]; s[(i<<1)-1][j<<1] = '$'; } for(int j = 1; j<=2*n-1; j++) { s[i<<1][j] = '$'; } } n<<=1; for(int i = 0; i<=n; i++) { s[0][i] = s[n][i] = '#'; s[i][0] = s[i][n] = '#';//边界标志。 } n--; long long ans = 0; for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { for(int k = 1; k<=n; k++) { if(s[i][j] == '0') { continue; }//注意:中间点为0的时候不能扩展qwq否则只有20分 X[0] = i+k*dx[0], Y[0] = j+k*dy[0]; X[1] = i+k*dx[1], Y[1] = j+k*dy[1]; X[2] = i+k*dx[2], Y[2] = j+k*dy[2]; X[3] = i+k*dx[3], Y[3] = j+k*dy[3]; if((s[X[0]][Y[0]] == '#') || (s[X[1]][Y[1]] == '#') || (s[X[2]][Y[2]] == '#') || (s[X[3]][Y[3]] == '#')) { break; } if((s[X[0]][Y[0]] == '0') || (s[X[1]][Y[1]] == '0') || (s[X[2]][Y[2]] == '0') || (s[X[3]][Y[3]] == '0')) { break; } if((s[X[0]][Y[0]] == '1') && (s[X[1]][Y[1]] == '1') && (s[X[2]][Y[2]] == '1') && (s[X[3]][Y[3]] == '1')) { ans++; } } } } printf("%lld\n", ans); return 0; }
T2王座下的背叛纲领
这个题我最后一秒写完的,没交上……
简化题意:给定一个
说一说我拿到题的思路:我一开始没啥特别好的思路,但是看到
这时候,我发现一个很重要的性质:就是,当你的上一行的状态确定时,你的下一行的操作情况也是确定的。因为你必须保证上一行全变成
很遗憾,发现这个性质后我没有好好利用,还是去想dp。最后才想到,其实对于第一行的每个初始状态,都有最多一个确定的方案去变换矩阵中的所有元素。那么,我们只需要枚举第一行的状态,然后往下搜索即可。注意,只有最后一行的终状态全为
Code:
#include<bits/stdc++.h> using namespace std; const int N = 1200, H = 1210; int T; int w, h; int fst[H]; int tsf[N], aft[N], opr[N], tot; //分别对应:变换方式(1为变换,0为不变),对应的最终结果(1为异或1,0为不异或),操作次数,方案总数。 int f_tsf[N];//某一状态对应的方案 void dfs(int pos, int x, int y, int op) { if(pos>=w) { tsf[++tot] = x; aft[tot] = y; opr[tot] = op; f_tsf[x] = tot; return; } dfs(pos+1, x, y, op); if(w == 1) { dfs(pos+1, (x|(1<<pos)), y^1, op+1); } else if(pos<1) { dfs(pos+1, (x|(1<<pos)), (y^3), op+1); } else if(pos == w-1) { dfs(pos+1, (x|(1<<pos)), (y^(3<<(pos-1))), op+1); } else { dfs(pos+1, (x|(1<<pos)), (y^(7<<(pos-1))), op+1); } } int mx; void print_fst(int aa[], int bb[]) { for(int i = 1; i<=tot; i++, puts("")) { for(int j = 0 ; j<w; j++) { printf("%d", ((aa[i]>>j)&1)); } printf(" "); for(int j = 0; j<w; j++) { printf("%d", ((bb[i]>>j)&1)); } } } long long ans; void init() { ans = 0x3f3f3f3f3f3f3f3f; memset(opr, 0x3f, sizeof(opr)); memset(fst, 0, sizeof(fst)); tot = 0; memset(tsf, 0, sizeof(tsf)); memset(aft, 0, sizeof(aft)); } void dfs2(int pos, int lst, long long sum, int opp) { if(pos>h) { if(lst == mx) ans = min(sum, ans); return; } int ned = lst^mx; int tmp = f_tsf[ned]; dfs2(pos+1, fst[pos]^tsf[opp]^aft[tmp], sum+opr[tmp], tmp); } int main() { scanf("%d", &T); while(T--) { init(); scanf("%d%d", &w, &h); for(int i = 0; i<w; i++) { for(int j = 1; j<=h; j++) { char tmp[2]; scanf("%s", tmp); if(tmp[0] == 'A') { fst[j]|=(1<<i); } } } mx = (1<<w)-1; dfs(0, 0, 0, 0); for(int i = 1; i<=tot; i++) { dfs2(2, fst[1]^aft[i], opr[i], i); } printf("%lld\n", ans); } return 0; }