方方正正

来源:互联网 发布:好吃的肉类零食知乎 编辑:程序博客网 时间:2024/06/15 22:09

方方正正Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 10(7 users)Total Accepted: 5(5 users)Rating: Special Judge: NoDescription

一个rc列的矩阵里的所有元素都为01,给出这个矩阵每一行的和以及每一列的和,那么是否存在这样一个矩阵满足条件呢,如果存在任意一个满足条件的矩阵则输出YES,如果不存在则输出NO

Input

(此行删除)第一行为一个正整数T(T <= 100),表示测试样例的组数。

每组测试数据第一行包含两个整数r,c,表示矩阵的行数和列数。

第二行包含r32位无符号数,表示矩阵每行的和。

第三行包含c32位无符号数,表示矩阵每列的和。

(1 <= r,c <= 100000)

处理到文件结束

Output如果存在这样的一个01矩阵,输出YES,否则输出NOSample Input


1 1

0

1

1 1

1

1


Sample Output

NO

YES

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<stack>#include<set>#include<map>#include<queue>#include<algorithm>using namespace std;int main(){    int m,n;    int na,nb;    int ma,mb;    int a;    int sa,sb;    while(~scanf("%d %d",&m,&n)){        na=0;nb=0;        ma=0;mb=0;        sa=0;sb=0;        while(m--){            scanf("%d",&a);            if(a){                na++;                sa+=a;            }            if(a>ma)                ma=a;        }        while(n--){            scanf("%d",&a);            if(a){                nb++;                sb+=a;            }            if(a>mb)                mb=a;        }        if(sa!=sb||ma>nb||mb>na)            printf("NO\n");        else            printf("YES\n");    }    return 0;}

标准题解

首先需要判断行和列的总和是否相等,因为它们都应该是整个矩阵的所有元素之和。如果他们不相等则这个矩阵肯定不存在。

这道题的贪心策略是,把列和从大到小枚举,对每个列和,按行和从大到小的顺序进行选择填上1,然后该行的行和减去1.这种贪心策略之所以有效,是因为这种策略会使各行的行和趋向于平均,尽可能地使行和减为零的情况推迟发生,而行和减为零意味着,当前可选的行数减少1,因此后面的计算可选择方法肯定比这种贪心的策略要少。

#include <stdio.h>#include <algorithm>using namespace std;const int size=100000;//最大行列数int a[size],b[size];//分别保存行和与列和int main(){int r,c,i,j;long long s,t;//枚举时比较的行和与列和总数while(scanf("%d%d",&r,&c)==2){//输入整数r,c直到文件结束for(i=0,s=0; i<r; i++){scanf("%d",&a[i]);//输入行和s+=a[i];//累加行和}for(i=0,t=0; i<c; i++){scanf("%d",&b[i]);//输入列和t+=b[i];//累加列和}if(s!=t){//如果行和与列和总数不相等printf("NO\n");//则不可能有解continue;}sort(a,a+r);//行和排序sort(b,b+c);//列和排序for(i=j=0,t=s=0; i<c; i++){//从大到小枚举列和t+=b[c-i-1];//当前已枚举的列和总数s+=r-j;//当前可用的行和总数while(j<r&&a[j]<i+1){//如果某行和小于枚举列数s-=i+1-a[j];//把行和总数多算出来的部分减去j++;}if(s<t) break;//如果可用行和小于当前列和则不可能有解}printf(i==c?"YES\n":"NO\n");//输出答案}return 0;}



0 0
原创粉丝点击