妈耶,这个这个大模拟,模拟了我俩小时。
这道题和紫书上上一道题一样,也是卡输入输出的。思路比较明确,设置数组记录是否使用过,记录当前元素序号,以后分开左右循环和上下循环,每次循环都保证从下一个有效单词开始,把它加入对应向量中。最后统一排序输出。
注意:
fill来填充顺序表时,最好全部填充,不然容易出现隐含错误。例如,如果我们想填充容量105105的矩阵的最左上角的23的单元格,那么fill(a[0],a[0]+2*3,0)是错误的。因为这样的话,会填充矩阵最前面的6个单元格,而不是我们想要的左上角。除了循环自己填充之外,最好的方法是全部填充。
但是,如果全部填充,效率就会下降。比如说,我只想填充一个12的区域,但是却需要填充105105次。所以,最好的方法还是手动循环填充,虽然看起来更繁琐,但是效率更快。这个点卡了我半个多小时。
除了上面那个最重要的注意点之外,其他注意点如下:
1.除最后一个用例之外,每两个用例之间都有一个空行分隔。
2.序号的输出宽度是3
下面是AC代码。这些world final题,果然有点东西。
#include <bits/stdc++.h>
#define N 105
using namespace std;
typedef pair<int,string> node;
char st[N][N];
int num[N][N];
bool used[N][N];
vector<node> acr,dow;
bool cmp(node a,node b) {
return a.first<b.first;
}
int main() {
// freopen("input.txt","ra",stdin);
// freopen("output.txt","wa",stdout);
int x,y,ct=0;
bool first=false;
while (scanf("%d",&x)&&x) {
getchar();
int cnt=0;
scanf("%d",&y);
getchar();
if (first&&y) printf("\n");
first=true;
fill(num[0],num[0]+N*N,0);
for (int i=0;i<x;i++) {
for (int j=0;j<y;j++) {
scanf("%c",&st[i][j]);
if (st[i][j]=='*') continue;
if ((i-1<0||j-1<0))num[i][j]=++cnt;
else if (st[i-1][j]=='*'||st[i][j-1]=='*')
num[i][j]=++cnt;
}
getchar();
}
fill(used[0],used[0]+N*N,false);
for (int i=0;i<x;i++) {
int j=0;
while (j<y) {
if (used[i][j]||num[i][j]==0) {j++;continue;}
string a="";
int be=j;
while (j<y&&st[i][j]!='*') {
a+=st[i][j];
used[i][j]=true;
j++;
}
acr.push_back(make_pair(num[i][be],a));
}
}
fill(used[0],used[0]+N*N,false);
for (int j=0;j<y;j++) {
int i=0;
while (i<x) {
if (used[i][j]||num[i][j]==0) {i++;continue;}
string a="";
int be=i;
while (i<x&&st[i][j]!='*') {
a+=st[i][j];
used[i][j]=true;
i++;
}
dow.push_back(make_pair(num[be][j],a));
}
}
sort(dow.begin(),dow.end(),cmp);
printf("puzzle #%d:\n",++ct);
printf("Across\n");
for (int i=0;i<(int)acr.size();i++)
printf("%3d.%s\n",acr[i].first,acr[i].second.c_str());
printf("Down\n");
for (int i=0;i<(int)dow.size();i++)
printf("%3d.%s\n",dow[i].first,dow[i].second.c_str());
dow.clear(),acr.clear();
}
return 0;
}