程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 枚舉+貪心 hdu-4334-Trouble

枚舉+貪心 hdu-4334-Trouble

編輯:C++入門知識

題目意思:

給5組數,每組含n個數(n<=200),在5組數中各選一個,問是否存在一種組合使這5個數的和為0。

解題思路:

這題數據很強,o(n^3*lgn過不了)

對於在兩組數各選一個使得和為定值,有一種貪心的算法,時間復雜度為(n*lgn,實際上就是排序的算法時間復雜度)。

所以可以把第二組和第三組數合並組合40000個數作為第二組,第四組和第五組合並成40000個數作為第三組。

分別排序。

1、然後枚舉第一組,初始時用p指針指向第二組中的第一個數,q指針指向第三組的最後一個數,以第二組為基准。

2、當三數大於0時,說明q指針後面的所有數與p指針後面的數肯定不行,大於當前的和值,同時說明p指針後面的只可能和q指針前面的湊,所以q指針往前移。

3、當三數小於0時,說明p與當前的q不行,p與q後面的也不行(由上一步得),p與q前面的更不行。所以p只能往後移。

貪心思想,所以最多只移動了40000+40000次。

所以總的時間復雜度為o(n^3).

代碼:

 

<SPAN style="FONT-SIZE: 18px">#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
ll s1[41000],s2[41000];
ll sa[6][210];
int cnt1,cnt2,n;

int main()
{
   int t;

   scanf("%d",&t);
   while(t--)
   {
      scanf("%d",&n);
      for(int i=1;i<=5;i++)
         for(int j=1;j<=n;j++)
            scanf("%I64d",&sa[i][j]);
      //sort(sa[1]+1,sa[1]+n+1);
      cnt1=cnt2=0;
      for(int i=1;i<=n;i++) 
         for(int j=1;j<=n;j++)
         {
            s1[++cnt1]=sa[2][i]+sa[3][j]; //把2、3組合並和把4、5組合並
            s2[++cnt2]=sa[4][i]+sa[5][j];
         }
      sort(s1+1,s1+cnt1+1);
      sort(s2+1,s2+cnt2+1);
      
      int t=1; //離散化一下,去掉相同的
      for(int i=2;i<=cnt1;i++)
         if(s1[i]!=s1[i-1])
            s1[++t]=s1[i];
      cnt1=t;
      t=1;
      for(int i=2;i<=cnt2;i++)
         if(s2[i]!=s2[i-1])
            s2[++t]=s2[i];
      cnt2=t;

     /* if(sa[1][n]+s1[cnt1]+s2[cnt2]<0)
      {
         printf("Yes\n");
         continue;
      }*/
      bool ans=false;
      for(int i=1;i<=n&&!ans;i++)
      {
         //if(sa[1][i]+s1[1]+s2[1]>0)
          //  break;
         for(int p=1,q=cnt2;p<=cnt1&&q>=1;) //貪心思想
         {
            ll tt=sa[1][i]+s1[p]+s2[q];
            if(tt==0)
            {
               ans=true;
               break;
            }
            else if(tt>0)
               q--;
            else
               p++;
         }
      }
      if(ans)
         printf("Yes\n");
      else
         printf("No\n");
   }

   return 0;
}


</SPAN>

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved