题目大意:
一个字符三角形可能出现'@' ,'*' ,'?'三种字符。三角形中只允许出现四种不同的@*的组合。'?'表示该字符未知。给出一个三角形,要求字符@出现最多和最少的次数分别是多少。
分析:
允许的字符排列有以下四种:
@ @ × ×
@×, ×@, ×@, @×
观察发现,一个规律:三角形的字符是否合法与前一行无关。也就是说,判断这个三角形是否合法,只需一行一行判断即可。
在继续观察可以得出另一个规律:某一行字符合法的充要条件是,@和×交替出现。
这两个结论都不难得出。有了这两个结论,可以想到用一个贪心的策略来构造未知的字符。
因为一行字符一定是@和×交替出现,那么要使得@最多,可以另该行第一个字符为@,然后向后递推。之后的每一个字符都可以确定下来。若出现矛盾的情况,说明假设不成立,只能修改第一个字符为×。求@出现最少也是一样的。
由于输入数据没有不合法的情况,处理起来很方便。
--------------------------------------------------------------------
/*
ZJU2058 The Archaeologist's Trouble II
*/
#include <stdio.h>
#include <string.h>
#define clr(a) memset(a,0,sizeof(a))
#define N 105
char other(char ch){
if(ch=='@') return '*';
else return '@';
}
int fillline(char a[][N],int i){
int j;
for(j=1;j<=i;j++){
if(a[i][j]=='?') a[i][j]=other(a[i][j-1]);
else if(a[i][j]==a[i][j-1]) return 0;
}
return 1;
}
int fill(char a[][N],int n,char ch){
int i,j,k;
char b[N];
for(i=0;i<n;i++){
strcpy(b,a[i]);
if(a[i][0]=='?') a[i][0]=ch;
if(!fillline(a,i)){
strcpy(a[i],b);
a[i][0]=other(ch);
fillline(a,i);
}
}
}
int count(char a[][N],int n){
int i,j,m=0;
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
if(a[i][j]=='@') m++;
return m;
}
int main()
{
int i,j,k,m,n;
int max,min;
char a[N][N],b[N][N];
while(scanf("%d",&n),n>=0){
//input
for(i=0;i<n;i++){
scanf("%s",a[i]);
strcpy(b[i],a[i]);
}
//work max
fill(a,n,'@');
fill(b,n,'*');
max=count(a,n);
min=count(b,n);
//output
printf("%d %d/n",max,min);
}
return 0;
}