小木棍 && 愤怒的小鸟

小木棍

题目描述

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050。

现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。

给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

输入输出格式

输入格式:

共二行。

第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65N65

(管理员注:要把超过5050的长度自觉过滤掉,坑了很多人了!)

第二行为NN个用空个隔开的正整数,表示NN根小木棍的长度。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<vector>
  7 #include<queue>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 using namespace std;
 12 const int maxn=100007;
 13 const int INF=0x7f7f7f7f;
 14 int n,m,sum,stp,ans=INF,req;
 15 int len[maxn],s[maxn],nxt[maxn];
 16 bool is[maxn],usd[maxn],bj; 
 17 void gettable(){
 18   for(int i=2;i<=sqrt(sum);i++){
 19     if(sum%i==0){
 20       if(i>=len[1]) s[++stp]=i;
 21       if(i!=(sum/i)) if(sum/i>=len[1]) s[++stp]=sum/i;
 22     }
 23   }
 24 }
 25 bool cmp(int a,int b){
 26   return a>b;
 27 }
 28 /*bool dfs(int now,int st,int lft){
 29   bool flg=false;
 30   if(lft==0&&st==sum/req) return true;
 31   if(lft==0){
 32     int i;
 33     for(i=1;i<=n;i++){
 34       if(!usd[i]){usd[i]=true;flg=true;break;}
 35     }
 36     if(flg) dfs(i,st+1,req-len[i]);
 37   }
 38   bool flag=false;
 39   for(int i=now+1;i<=n;i++){
 40     if(usd[i]) continue;
 41     if(lft>=len[i]){
 42       usd[i]=true;flag=true;
 43       if(dfs(i,st,lft-len[i])) return true;
 44       else return false;
 45       usd[i]=false;
 46     }
 47   }
 48   if(!flag) return false;
 49 }*/
 50 void dfs(int k,int last,int rest){
 51   int i,j;
 52   if(rest==0){
 53     if(k==(sum/req)){bj=1;return;}
 54     for(i=1;i<=n;i++)
 55       if(!usd[i]){usd[i]=true;break;}
 56     dfs(k+1,i,req-len[i]);
 57     usd[i]=false;
 58     if(bj) return;
 59   }
 60   int l=last+1, r=n, mid;
 61   while(l<=r){
 62     mid=(l+r)/2;
 63     if(len[mid]<=rest) r=mid-1;
 64     else l=mid+1;
 65   }
 66   for(i=l;i<=n;i++){
 67     if(!usd[i]){ 
 68       usd[i]=1;
 69       dfs(k,i,rest-len[i]);
 70       usd[i]=0;
 71       if(bj) return;   
 72       if(rest==len[i]) return; 
 73       i=nxt[i];
 74       if(i==n) return;
 75     }
 76   }
 77 }
 78 int main(){
 79   cin>>m;
 80   for(int i=1;i<=m;i++){
 81     int a;cin>>a;if(a>50) continue;
 82     len[++n]=a;sum+=len[n];
 83   }
 84   sort(len+1,len+n+1,cmp);
 85   gettable();
 86   sort(s+1,s+n+1,cmp);
 87   nxt[n]=n;
 88   for(int i=n-1;i>=1;i--){
 89     if(len[i]==len[i+1]) nxt[i]=nxt[i+1];
 90     else nxt[i]=i;
 91   }
 92   for(int i=1;i<=stp;i++){
 93       if(is[i]) continue;
 94       memset(usd,false,sizeof(usd)); 
 95       bj=false;usd[1]=true;req=s[i];
 96     dfs(1,1,req-len[1]);
 97     if(!bj){
 98       for(int j=i+1;j<=stp;j++){
 99         if(s[i]%s[j]==0) is[j]=true;
100       }
101     }
102     else ans=min(ans,s[i]);  
103   }
104   if(ans==INF) cout<<sum<<endl;
105   else cout<<ans<<endl;
106 } 

 愤怒的小鸟

这样搜会T一半的点:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long double dd;
 8 const int maxn=27;
 9 const int INF=0x7f7f7f7f;
10 const dd eps=1e-8;
11 int t,n,m,ans;
12 dd x[maxn],y[maxn];
13 bool flag,bflg[maxn][maxn];
14 bool usd[maxn],busd[maxn][maxn][maxn];
15 dd geta(dd x1,dd x2,dd y1,dd y2){
16   dd ret;
17   ret=(x1*y2-y1*x2)/((x1*x2)*(x2-x1));
18   return ret;
19 }
20 dd getb(dd x1,dd x2,dd y1,dd y2){
21   dd ret;
22   ret=(y2*x1*x1-y1*x2*x2)/((x1*x2)*(x1-x2));
23   return ret;
24 }
25 void cpy(int zhu,int niao){
26   for(int i=1;i<=n;i++)
27     busd[zhu][niao][i]=usd[i];
28   bflg[zhu][niao]=flag;
29 }
30 void recpy(int zhu,int niao){
31   for(int i=1;i<=n;i++)
32     usd[i]=busd[zhu][niao][i];
33   flag=bflg[zhu][niao];
34 }
35 bool zai(dd x,dd y,dd a,dd b){
36   dd tmp=a*x*x+b*x;
37   if(fabs(tmp-y)<eps) return true;
38   return false; 
39 }
40 void dfs(int zhu,int niao){
41   if(niao>ans||niao>n) return;
42   if(m==1){
43       int tmp;
44     if(n%3!=0) tmp=n/3+1+1;
45     else tmp=n/3+1;
46     if(niao>tmp) return;
47   }
48   if(m==2){if(zhu<(n/3)&&!flag) return;}
49   if(zhu==0){
50     if(m==0) ans=min(ans,niao);
51     if(m==1) ans=min(ans,niao);
52     if(m==2){
53       if(flag) ans=min(ans,niao);
54     }
55   }
56   for(int i=1;i<=n;i++){
57       if(usd[i]) continue;
58       bool vis=false;
59     for(int j=i+1;j<=n;j++){
60       if(!usd[i]&&!usd[j]){
61         dd a=geta(x[i],x[j],y[i],y[j]);
62         dd b=getb(x[i],x[j],y[i],y[j]);
63         if(a<=0){
64           int tmp=zhu;
65           cpy(zhu,niao);
66           for(int k=1;k<=n;k++){
67               if(usd[k]) continue;
68             if(zai(x[k],y[k],a,b)){
69               usd[k]=true;tmp--;
70             }
71           }
72           if((zhu-tmp)>=(n/3)) flag=true;
73           vis=true;dfs(tmp,niao+1);
74           recpy(zhu,niao);
75         }
76       }
77     }
78     if(!vis){
79       usd[i]=true;dfs(zhu-1,niao+1);
80       usd[i]=false;
81     }
82   }
83 }
84 int main(){
85   //freopen("a.in","r",stdin);
86   scanf("%d",&t);
87   while(t--){
88       ans=INF;flag=false;memset(usd,false,sizeof(usd));
89     memset(x,0,sizeof(x));memset(y,0,sizeof(y));
90     scanf("%d%d",&n,&m);
91     for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
92     dfs(n,0);if(ans==INF) ans=n;
93     printf("%d
",ans);
94   }
95 } 

这样搜比较好:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 typedef double dd;
 8 const int maxn=27;
 9 const int INF=0x7f7f7f7f;
10 const dd eps=1e-8;
11 int t,n,m,ans;
12 dd x[maxn],y[maxn],ai[maxn],bi[maxn],xi[maxn],yi[maxn];
13 bool zai(dd x,dd y,dd a,dd b){
14   dd tmp=a*x*x+b*x;
15   if(fabs(tmp-y)<eps) return true;
16   return false; 
17 }
18 bool tong(dd x,dd y){
19   return fabs(x-y)<eps;
20 }
21 dd geta(dd x1,dd x2,dd y1,dd y2){
22   dd ret;
23   ret=(x1*y2-y1*x2)/((x1*x2)*(x2-x1));
24   return ret;
25 }
26 dd getb(dd x1,dd x2,dd y1,dd y2){
27   dd ret;
28   ret=(y2*x1*x1-y1*x2*x2)/((x1*x2)*(x1-x2));
29   return ret;
30 }
31 void dfs(int z,int u,int v){
32   if(u+v>=ans) return;
33   if(z>n){ans=min(ans,u+v);return;}
34   bool vis=false;
35   for(int i=1;i<=u;i++){
36     if(zai(x[z],y[z],ai[i],bi[i])){
37       vis=true;dfs(z+1,u,v);break;
38     }
39   }
40   if(!vis){
41     for(int i=1;i<=v;i++){
42       dd xx=xi[i];dd yy=yi[i];
43       if(tong(xx,x[z])) continue;
44       dd a=geta(x[z],xx,y[z],yy);
45       dd b=getb(x[z],xx,y[z],yy);
46       if(a<0){
47         ai[u+1]=a;bi[u+1]=b;
48         dd tm=xi[i];dd tp=yi[i];
49         for(int j=i;j<v;j++){
50           xi[j]=xi[j+1];yi[j]=yi[j+1];
51         }
52         dfs(z+1,u+1,v-1);
53         for(int j=v;j>i;j--){
54           xi[j]=xi[j-1];yi[j]=yi[j-1];
55         }
56         xi[i]=tm;yi[i]=tp;
57       }
58     }
59     xi[v+1]=x[z];yi[v+1]=y[z];
60     dfs(z+1,u,v+1);
61   }
62 }
63 int main(){
64   //freopen("a.in","r",stdin); 
65   scanf("%d",&t);
66   while(t--){
67     scanf("%d%d",&n,&m);ans=INF;
68     memset(ai,0,sizeof(ai));memset(bi,0,sizeof(bi));
69     memset(xi,0,sizeof(xi));memset(yi,0,sizeof(yi)); 
70     for(int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
71     dfs(1,0,0);printf("%d
",ans);
72   }
73 }

 正解是状压:

原文地址:https://www.cnblogs.com/lcan/p/9885374.html