首页 > 技术文章 > [ CodeVS冲杯之路 ] P2456

hadilo 2016-09-30 17:50 原文

  不充钱,你怎么AC?

  题目:http://codevs.cn/problem/2456/

 

  用贪心的思想,木材当然要尽量分成多的木板,而大的木材能够分成大木板,但是小的木材不一定能够分成大的木板,所以木板和木材都是从小到大开始选,然后要保证剩余的木材最少

  那么将木板和木材排序,对于每个木材,把能够分的小木板尽量分掉,如果遇到更大的木板则把最小的木板腾出来,然后在加上,这样保证剩余的木材最少

  因为是上午写得这道题,思路可能不连贯了,代码应该描述的很清楚

  虽然贪心在CodeVS上可以过,但是它是有数据可以卡掉的,而正解是DFS

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 
 9 const int N=51,M=1024;
10 int a[N],b[M],next[M];
11 bool f[M];
12 int main()
13 {
14     int n,i,j,m,k,now,ans=0,x,y;
15     scanf("%d",&n);
16     for (i=1;i<=n;i++) scanf("%d",&a[i]);
17     sort(a+1,a+1+n);
18     scanf("%d",&m);
19     for (i=1;i<=m;i++) scanf("%d",&b[i]);
20     sort(b+1,b+1+m);
21     for (i=1;i<=n;i++)
22         {
23             now=a[i];
24             for (j=0;j<=m;j++) next[j]=0;
25             for (j=1;j<=m;j++)
26                 {
27                     if (f[j]) continue;
28                     if (now>=b[j])
29                         {
30                             now-=b[j];
31                             f[j]=1;
32                             ans++;
33                             next[j]=next[0];
34                             next[0]=j;
35                         }
36                     else
37                         {
38                             k=x=0;
39                             while (now+b[next[k]]>=b[j]) k=next[x=k];
40                             if (k)
41                                 {
42                                     next[x]=next[k];
43                                     f[k]=0;
44                                     f[j]=1;
45                                     next[j]=next[0];
46                                     next[0]=j;
47                                     now+=b[k]-b[j];
48                                 }
49                         }
50                 }
51         }
52     printf("%d\n",ans);
53     return 0;
54 }

 

  下面是DFS的正解,贴的别人的代码

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 
 9 #define N 1100
10 
11 int n,m;
12 int sum1,ans;
13 int tim,res;
14 
15 int a[N],b[N],c[N],sum[N];
16 
17 int work(int x,int k)
18 {
19     if (!x)
20         return true;
21     if (tim>res)
22         return false;
23     for (int i=k;i<=n;i++)
24         if (a[i]>=b[x])
25         {
26             a[i]-=b[x];
27             if (a[i]<b[1])
28                 tim+=a[i];
29             if (b[x]==b[x-1])
30             {
31                 if (work(x-1,i))
32                     return true;
33             }
34             else if (work(x-1,1))
35                 return true;
36             if (a[i]<b[1])
37                 tim-=a[i];
38             a[i]+=b[x];
39         }
40     return false;
41 }
42 
43 int main()
44 {
45     scanf("%d",&n);
46     for (int i=1;i<=n;i++)
47         scanf("%d",&a[i]),sum1+=a[i],c[i]=a[i];
48     scanf("%d",&m);
49     for (int i=1;i<=m;i++)
50         scanf("%d",&b[i]);
51     sort(a+1,a+n+1);
52     sort(b+1,b+m+1);
53     for (int i=1;i<=m;i++)
54         sum[i]=b[i]+sum[i-1];
55     int l=0,r=m;
56     while (l!=r)
57     {
58         int mid=(l+r+1)>>1;
59         tim=0;
60         res=sum1-sum[mid];
61         if (work(mid,1))
62             l=mid;
63         else
64             r=mid-1;
65         for (int i=1;i<=n;i++)
66             a[i]=c[i];
67     }
68     printf("%d\n",l);
69     return 0;
70 }

 

推荐阅读