Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5388 Accepted Submission(s): 1494
解题思路:开始写了搜索,但是一直超时。然而超时好像是必然的,没办法剪枝。其实可以将前1、2行合成一行a,将3、4行合成一行b,从小到大排序。枚举剩下的最后一行c,枚举a,逆序枚举b。贪心思想在如果b的当前值跟a和c的和小于0,那么可以直接让a的指针加一,如果大于0,可以让b的指针减一,如果逆序遍历完b或正序遍历完a以后还没找到,那么就继续枚举c。
#include<bits/stdc++.h> using namespace std; typedef long long INT; INT Map[6][210]; INT a[42000]; INT b[42000]; INT c[210]; int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=5;i++){ for(int j=0;j<n;j++){ scanf("%lld",&Map[i][j]); } } int na=0,nb=0,nc=0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ a[na++]=Map[1][i]+Map[2][j];//合并1、2行 b[nb++]=Map[3][i]+Map[4][j];//合并3、4行 } } int nn=n*n; sort(a,a+nn); //递增排序 sort(b,b+nn); //递增排序 na=1,nb=1,nc=1; for(int i=1;i<nn;i++){ //去重 if(a[i]!=a[i-1]){ a[na++]=a[i]; } } for(int i=1;i<nn;i++){ //去重 if(b[i]!=b[i-1]){ b[nb++]=b[i]; } } c[0]=Map[5][0]; for(int i=1;i<n;i++){ //去重 if(Map[5][i]!=Map[5][i-1]){ c[nc++]=Map[5][i]; } } int flag=0; for(int i=0;i<nc&&(!flag);i++){ //n的复杂度 for(int j=0,k=nb-1;k>=0&&j<na; ){//n*n的复杂度 INT cc=c[i]+a[j]+b[k]; if(cc<0){ //降低复杂度。模拟跳出一层循环 j++; }else if(cc==0){ flag=1; break; }else{ k--; } } } if(flag){ puts("Yes"); }else { puts("No"); } } return 0; }
HDU 4334——Trouble——————【贪心&水题】
原文:http://www.cnblogs.com/chengsheng/p/4758368.html