• 10.21T8 rand()随机化/背包


    Description

    N(1 <= N <= 20)个干草堆,每堆的体积大小为Si(1 <= Si <= 100),需要分装到三个谷仓里。要求这三谷仓分得尽量平均(每堆草不可分割),即最大的一堆最小。请求出这最大的一个谷仓分得的体积。

    Input

    第一行: 整数 N.
    第 2..1+N行:每行一个整数表示第第i堆的体积Si.

    Output

    第1行:最大谷仓分得的干草堆体积和

    Sample Input

    8
    14
    2
    5
    15
    8
    9
    20
    4

    Sample Output

    26
     
     
     
    此题使用堆然后直接看人品随机化就可以了
    23333333
    使用我的生日20020731做种子就AC了哈哈哈哈哈哈
    code:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<ctime>
     5 #include<cstdlib>
     6 using namespace std;
     7 priority_queue<int,vector<int>,greater<int> >q;
     8 int a[30];
     9 int main() {
    10     srand(20020731);
    11     int n;
    12     cin>>n;
    13     for(int i=1; i<=n; i++) {
    14         cin>>a[i];
    15         q.push(a[i]);
    16     }
    17     int min0=0x3f3f3f3f;
    18     for(int o=1; o<=1200000; o++) {
    19         int b[3]= {0,0,0},max0=0;
    20         for(int i=1; i<=n; i++) {
    21             int now=q.top();
    22             q.pop();
    23             b[(rand())%3]+=now;
    24         }
    25         max0=max(b[0],max(b[1],b[2]));
    26         min0=min(min0,max0);
    27         for(int i=1; i<=n; i++) {
    28             q.push(a[i]);
    29         }
    30     }
    31     cout<<min0;
    32     return 0;
    33 }

    当然我们除此之外还有背包算法

    令f[i][j]表示第一个谷仓体积为i,第二个为j是否存在,于是我们就可以直接暴力跑背包

    当然因为转移的时候好像为了避免滚动数组的思考难度就用了两个数组复用

    code:

     1 #include <iostream>
     2 using namespace std;
     3 const int MAXS = 700;
     4 
     5 int n, bale, tsum;
     6 bool good[2][MAXS+100][MAXS+100];
     7 
     8 int main()
     9 {
    10     for (int i = 0; i < 2; i++)
    11         for (int j = 0; j < MAXS; j++)
    12             for (int k = 0; k < MAXS; k++)
    13                 good[i][j][k] = false;
    14     good[0][0][0] = true;
    15     tsum = 0;
    16 
    17     fin >> n;
    18     for (int i = 0; i < n; i++)
    19     {
    20         fin >> bale;
    21         tsum += bale;
    22         for (int j = 0; j < MAXS; j++)
    23             for (int k = 0; k < MAXS; k++)
    24             {
    25                 if (good[i%2][j][k])
    26                 {
    27                     good[(i+1)%2][j][k] = true;
    28                     good[(i+1)%2][j+bale][k] = true;
    29                     good[(i+1)%2][j][k+bale] = true;
    30                 }
    31             }
    32     }
    33 
    34     int ans = MAXS;
    35     for (int i = 0; i < MAXS; i++)
    36         for (int j = 0; j < MAXS; j++)
    37             if (good[n%2][i][j])
    38                 ans = min (ans, max (i, max (j, tsum - (i + j))));
    39     fout << ans <<"
    ";
    40     return 0;
    41 }

    爆搜也是可以的

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int a[25],n,ans=0x7fffffff;
     5 void dfs(int k,int x,int y,int z){
     6     if(k==n+1){ans=min(ans,max(max(x,y),z));return ;}
     7 //可行性减枝
     8     if(ans-a[k]>x)dfs(k+1,x+a[k],y,z);
     9     if(ans-a[k]>y&&x!=y)dfs(k+1,x,y+a[k],z);
    10     if(ans-a[k]>z&&x!=z&&y!=z)dfs(k+1,x,y,z+a[k]);
    11 }
    12 int main(){
    13     scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    14     dfs(1,0,0,0);printf("%d",ans);
    15     return 0;
    16 }

    神仙做法:排完序之后可以交换

    code:

     1 #include<iostream>
     2 #include<iomanip>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 int n;
     9 int s[200]={0};
    10 int minv[3];
    11 int ob[3][200]={0};
    12 int cnt[3]={0};
    13 bool cmp(int a,int b){return a>b;}
    14 int get_maxpos(){int maxpos,vmax=0;for(int k=0;k<=2;k++)if(minv[k]>vmax){maxpos=k;vmax=minv[k];}return maxpos;}
    15 int get_minpos(){int minpos,vmin=0x7fffffff;for(int k=0;k<=2;k++)if(minv[k]<vmin){minpos=k;vmin=minv[k];}return minpos;}
    16 void tiaozheng(int a,int b){//通过枚举交换a,b的物品,使最大值最小 
    17     bool mark=0;
    18     for(int i=1;i<=cnt[a];i++){
    19         for(int j=1;j<=cnt[b];j++){
    20             if(max(minv[a]-ob[a][i]+ob[b][j],minv[b]-ob[b][j]+ob[a][i])<max(minv[a],minv[b])){//如果交换后最大值最小 
    21                 minv[a]=minv[a]-ob[a][i]+ob[b][j];
    22                 minv[b]=minv[b]-ob[b][j]+ob[a][i];
    23                 swap(ob[a][i],ob[b][j]);//交换两个物品 
    24                 mark=1;//标记交换过 
    25             }
    26         }
    27     }
    28     if(!mark)return;//如果之前有交换,继续交换最大和最小 
    29     int maxpos=get_maxpos(),minpos=get_minpos();
    30     if(minpos!=maxpos)tiaozheng(minpos,maxpos);
    31 }
    32 int main(){
    33     scanf("%d",&n);
    34     for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    35     
    36     sort(s+1,s+n+1,cmp);//按从大到小排序 
    37 
    38     minv[0]=s[1];//初始赋值 
    39     ob[0][1]=s[1];
    40     cnt[0]=1;
    41     //每步都保证当前最优 
    42     for(int i=2;i<=n;i++){
    43         int maxpos,minpos=get_minpos();//得到当前最小位置,加入s[i] 
    44         minv[minpos]+=s[i];
    45         cnt[minpos]++;
    46         ob[minpos][cnt[minpos]]=s[i];
    47         maxpos=get_maxpos();minpos=get_minpos();
    48         if(minpos!=maxpos)tiaozheng(minpos,maxpos);//先交换最大的和最小的
    49         tiaozheng(0,1);//尝试交换既不是最大也不是最小的
    50         tiaozheng(2,1);
    51         tiaozheng(0,2);
    52     }
    53     int ans=0;
    54     ans=max(minv[0],minv[1]);
    55     ans=max(ans,minv[2]);
    56     cout<<ans;
    57     return 0;
    58 }

    over  哈哈哈哈哈哈哈哈哈哈哈哈嗝

  • 相关阅读:
    sql 生成开始日期到结束日期相差天数或日期
    自定义表做存储过程变量
    [转]html 移动互联网终端的javascript touch事件,touchstart, touchend, touchmove
    [转]JQuery.Ajax之错误调试帮助信息
    解决IOS safari在input focus弹出输入法时不支持position fixed的问题
    查看 存储过程的执行时间
    ListView
    android矩阵详解
    跳出圈子 “莫忘初心,方得始终”
    Eclipse使用
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9827253.html
Copyright © 2020-2023  润新知