D - 错误的算法CSU - 1926
有道题目是这样的:
输入一个 n 行 m 列网格,找一个格子,使得它所在的行和列中所有格子的数之和最大。如果答 案不唯一,输出任意解即可。比如,在下面的例子中,最优解是(1,3),即第一行和的三列的交 点(行从上到下编号为1~n,列从左到右编号为 1~m),所有 7 个数之和为 35。
快要比赛的时候,有一个裁判想到了这样一个算法:
首先找一行 r(1<=r<=n) 使得该行所有数之和最大,然后找一列 c(1<=c<=m) 使得该列 所有数之和最大,最后直接输出(r,c)。如果有多个满足条件的 r,输出最小的 r。对 于 c 同样处理。
显然,这个算法是错的,但它竟然通过了大部分测试数据!你能找出那些让这个错误算法得到 正确结果的“弱”数据,以便裁判们改进这些数据吗?
4 4 5 5 5 5 1 1 5 1 1 1 5 1 1 1 5 1 5 4 2 5 1 1 1 1 9 1 1 1 1 1 1 1 1 1 1 1 1 1
Case 1: WeakCase 2: Strong
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int a[505][505]; int n,m; int cmp() { int max =0; int maxx,maxy,sum; int i,j,k,t; for( i=1; i<=n; i++) { for(j=1; j<=m; j++) { maxx = 0; maxy = 0; sum = 0; for( k=1; k<=m; k++) { maxx+=a[i][k]; } for( t=1; t<=n; t++) { maxy+=a[t][j]; } sum = maxx + maxy - a[i][j]; if(sum>max) { max = sum; } } } return max; } int main() { int t=1; int i,j,sum; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1; i<=n; i++) { for(j=1; j<=m; j++) { scanf("%d",&a[i][j]); } } printf("Case %d: ",t++); int max =0,maxx=0,maxy=0,ll,li; for( i=1; i<=n; i++) { sum =0; for( j=1; j<=m; j++) { sum+=a[i][j]; } if(sum>maxx) { maxx = sum; ll = i; } } for( i=1; i<=m; i++) { sum =0; for(j=1; j<=n; j++) { sum+=a[j][i]; } if(sum>maxy) { maxy = sum; li = i; } } max = maxy + maxx - a[ll][li]; if(max==cmp()) { printf("Weak\n"); } else { printf("Strong\n"); } } return 0; }