题意:给出一个乘法表,其中有的数字不知道,但是知道已知数字的相对位置,问是否是题目中乘法表的一部分。
如果所给的表中没有数字输出 Yes
如果有一个数字 n 的话,分解因数与其坐标比较判断。枚举到根号 n 即可。
如果大于等于两个数字的话,先判断第一个数字,如果第一个数字的坐标满足条件,再根据坐标差计算之后的数字看是否相等。
所以此题不需要解方程甚至解方程组。
还有几个需要注意的地方:
- 存储时只存储有数字的点,这样就不用遍历全图
- 用 getline 读取每一行,因为 getline 支持 string 类,但是 getline 会吃掉输入行列时那个回车,所以要加个 getchar
#include<cstring> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<iostream> #include<algorithm> using namespace std; int r1, c1; //第一个数的坐标 int r, c; int sum; //表中数字个数 struct point{ //存储每个数的值和坐标 int num, r, c; }p[1000005]; bool judge1(int x, int y){ //判断一个点是否满足条件 int n = p[0].num; for(int i = 1; i <= sqrt(n); i++){ int k = n/i; if(k*i == n){ //能整除 if((k>=x && i>=y) || (k>=y && i>=x)) return 1; } } return 0; } bool judge2(){ int n = p[0].num; for(int i = 1; i <= sqrt(n); i++){ int k = n/i; if(k*i == n){ if(k>=r1 && i>=c1){ int flag = 0, j; for(j = 1; j < sum; j++){ int xx = p[j].r-r1; int yy = p[j].c-c1; if((k+xx)*(i+yy) != p[j].num){ flag = 1; break; } } if(j == sum && !flag) return 1; } //i和k互换 if(i>=r1 && k>=c1){ int flag = 0, j; for(j = 1; j < sum; j++){ int xx = p[j].r-r1; int yy = p[j].c-c1; if((i+xx)*(k+yy) != p[j].num){ flag = 1; break; } } if(j == sum && !flag) return 1; } } } return 0; } int main(){ //freopen("a.txt", "r", stdin); int t; scanf("%d", &t); for(int cas = 1; cas <= t; cas++){ scanf("%d %d", &r, &c); string s; int m = 0, n; sum = 0; getchar(); for(int i = 1; i <= r; i++){ getline(cin, s); int cnt = 1; for(int j = 0; j < s.length(); j++){ if(s[j]!='?' && s[j]!=' '){ n = s[j]-'0'; m = m*10+n; } if(s[j] == ' ' || j == s.length()-1){ p[sum].num = m; p[sum].r = i; p[sum].c = cnt; if(m!=0){ sum++; if(sum == 1){ r1 = i; c1 = cnt; } } cnt++; m = 0; } } } if(sum == 0) printf("Case #%d: Yesn", cas); else if(sum == 1){ printf("Case #%d: ", cas); if(judge1(r1, c1)){ printf("Yesn"); }else printf("Non"); }else{ printf("Case #%d: ", cas); if(judge2()){ printf("Yesn"); }else printf("Non"); } } return 0; }