目录
题目:
解答:
#include <stdio.h>
int main()
{
int N, M, Q;
scanf("%d %d %d", &N, &M, &Q); //输入N、M、Q的值
int i = 0;
int T[1000] = { 0 }; //因为Q的最大值为1000,T的大小与Q相等
int C[1000] = { 0 }; //因为Q的最大值为1000,C的大小与Q相等
for (i = 0;i < Q;i++) //输入T、C的值
scanf("%d %d", &T[i], &C[i]);
int j = 0;
int cnt1 = 0, cnt2 = 0, cnt3 = 0;
for (i = 0;i < Q;i++) {
if (T[i] == 0)
cnt1++; //cnt1记录有多少行会受到攻击(包括了重复的行数)
//printf("cnt1=%d\n",cnt1);
for (j = i + 1;j < Q;j++) {
if (T[i] == 0 && T[j] == 0 && C[i] == C[j]) {
cnt2++; //cnt2为行上重复的次数
//printf("cnt2=%d\n",cnt2);
break; //第一次重复时就跳出循环,否则cnt2记录的循环次数会重复(理由在下文)
}
if (T[i] == 1 && T[j] == 1 && C[i] == C[j]) {
cnt3++; //cnt3为列上重复的次数
//printf("cnt3=%d\n",cnt3);
break; //第一次重复时就跳出循环,否则cnt3记录的循环次数会重复(理由在下文)
}
}
}
long long int safe = 0;
safe = N * M - cnt1 * M - (Q - cnt1) * N + cnt2 * M
+ cnt3 * N + (cnt1 - cnt2) * (Q - cnt1 - cnt3);
/*
N * M 为总共的格子数
cnt1 * M 为行上有危险的格子数
(Q - cnt1) * N 为行上有危险的格子数
cnt2 * M 为行上重复的格子数
cnt3 * N 为行上重复的格子数
(cnt1 - cnt2) * (Q - cnt1 - cnt3) 为行和列相交的格子数
*/
printf("%lld", safe);
return 0;
}
关于为什么cnt1和cnt2记录第一次重复后就要跳出循环:
假设数字1代表这个条件: ( T[i] == 0 && T[j] == 0 && C[i] == C[j] ) 为true时
很明显如果是上面这种情况的时候,cnt2在正确的情况下,cnt2 = 5
假如记录第一次重复后没有跳出循环:
很明显如果是上面这种情况的时候,cnt2 = 15,比正确值5大了很多
假如记录第一次重复后就跳出循环:
上图这种情况,cnt2 = 5,正确
cnt3的理由同上