最近很是浮躁啊。。div3做出来两题。。rating1234->1230...
究其原因还是因为自己菜吧
不谈了,补个题
不多说,少了一个break
也不想说,爆int
E1. Stars Drawing (Easy Edition)
E2. Stars Drawing (Hard Edition)
直接两题一起放上来吧,题意都是一样的,数据范围不一样。
大概就是给你一个图,让你在里面找星星,看能否覆盖所有的星号,能就输出各个星星的中心点和半径,不能就-1
Easy Edition : 3 <= n, m <= 100
Hard Edition : 3 <= n, m <= 1000
简单版本没啥好说的,n^3暴力就能过,说一下优化
预处理出来每个点的相邻的上下左右的星星个数
再遍历每个点,取一个上下左右的最小值(合法),然后把这个点记录下来
再check一下由记录下来的星星组成的图是否与给出的重合,不行-1,可以就输出答案
时间复杂度O(n *m * C),C是常数,不会超过10
空间复杂度不谈~
这题数据感觉略水,我用的重新建图再判断是否重合的方法感觉在极限数据(n==m==1000 除了四角都是*)的情况下会超时,不过800+ms就跑过了。。。
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1005;
using namespace std;
char s[maxn][maxn], s2[maxn][maxn];
int l[maxn][maxn], r[maxn][maxn], u[maxn][maxn], d[maxn][maxn];
int len[maxn][maxn];
struct node{
int x, y, s;
node(){}
node(int tx, int ty, int ts){
x = tx, y = ty, s = ts;
}
} f[maxn*maxn];
int main()
{
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
s2[i][j] = '.';
}
}
for(int i = 1; i <= n; i++) scanf(" %s", s[i] + 1);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] == '*') l[i][j] = l[i][j-1] + 1;
}
}
for(int i = 1; i <= n; i++){
for(int j = m; j >= 1; j--){
if(s[i][j] == '*') r[i][j] = r[i][j+1] + 1;
}
}
for(int j = 1; j <= m; j++){
for(int i = 1; i <= n; i++){
if(s[i][j] == '*') u[i][j] = u[i-1][j] + 1;
}
}
for(int j = 1; j <= m; j++){
for(int i = n; i >= 1; i--){
if(s[i][j] == '*') d[i][j] = d[i+1][j] + 1;
}
}
int cnt = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] == '*'){
len[i][j] = min(l[i][j], min(r[i][j], min(u[i][j], d[i][j])));
len[i][j]--;
if(!len[i][j]) continue;
int t = len[i][j];
f[++cnt] = node(i, j, len[i][j]);
for(int k = i - len[i][j]; k <= i + len[i][j]; k++) s2[k][j] = '*';
for(int k = j - len[i][j]; k <= j + len[i][j]; k++) s2[i][k] = '*';
}
}
}
bool flag = true;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] != s2[i][j]) flag = false;
}
}
if(!flag) puts("-1");
else{
printf("%d\n", cnt);
for(int i = 1; i <= cnt; i++){
printf("%d %d %d\n", f[i].x, f[i].y, f[i].s);
}
}
return 0;
}
参考了别人代码,想了一个优化,使得复杂度在O(n*m*C)
类似区间求和的思想,预处理的时候+1/-1操作
用两个二维数组W和S来求出前缀和,再查询就行了
优化完405ms,当然,这是数据的问题,否则优化的时间不会是常数级的
AC Code2
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1005;
using namespace std;
char s[maxn][maxn], s2[maxn][maxn];
int l[maxn][maxn], r[maxn][maxn], u[maxn][maxn], d[maxn][maxn];
int len[maxn][maxn], W[maxn][maxn], S[maxn][maxn];
struct node{
int x, y, s;
node(){}
node(int tx, int ty, int ts){
x = tx, y = ty, s = ts;
}
} f[maxn*maxn];
int main()
{
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) scanf(" %s", s[i] + 1);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] == '*') l[i][j] = l[i][j-1] + 1;
}
}
for(int i = 1; i <= n; i++){
for(int j = m; j >= 1; j--){
if(s[i][j] == '*') r[i][j] = r[i][j+1] + 1;
}
}
for(int j = 1; j <= m; j++){
for(int i = 1; i <= n; i++){
if(s[i][j] == '*') u[i][j] = u[i-1][j] + 1;
}
}
for(int j = 1; j <= m; j++){
for(int i = n; i >= 1; i--){
if(s[i][j] == '*') d[i][j] = d[i+1][j] + 1;
}
}
int cnt = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] == '*'){
len[i][j] = min(l[i][j], min(r[i][j], min(u[i][j], d[i][j])));
len[i][j]--;
if(!len[i][j]) continue;
int t = len[i][j];
f[++cnt] = node(i, j, len[i][j]);
W[i][j-t]++, W[i][j+t+1]--;
S[i-t][j]++, S[i+t+1][j]--;
}
}
}
bool flag = true;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
W[i][j] += W[i][j-1], S[i][j] += S[i-1][j];
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s[i][j] == '*' && !W[i][j] && !S[i][j]) flag = false;
}
}
if(!flag) puts("-1");
else{
printf("%d\n", cnt);
for(int i = 1; i <= cnt; i++){
printf("%d %d %d\n", f[i].x, f[i].y, f[i].s);
}
}
return 0;
}
本文介绍了一道编程竞赛题目“Stars Drawing”的解决方案,包括Easy Edition与Hard Edition两个难度级别。通过对原始数据进行预处理,利用优化算法实现复杂度从O(n^3)到O(n*m*C)的降低,确保在大规模数据输入下也能高效运行。
198

被折叠的 条评论
为什么被折叠?



