zoukankan      html  css  js  c++  java
  • 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  哈哈哈哈哈哈哈哈哈哈哈哈嗝

  • 相关阅读:
    清北学堂模拟赛d1t5 拍照(photo)
    清北学堂模拟赛d1t4 一道图论好题(graph)
    清北学堂模拟赛d1t3 听音乐(music)
    Android(java)学习笔记167:横竖屏切换时Activity的生命周期
    Android(java)学习笔记166:上下文的区分
    Android(java)学习笔记165:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例的优化:请求码和结果码)
    Android(java)学习笔记164:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例)
    Android(java)学习笔记163:开发一个多界面的应用程序之界面间数据传递
    Android(java)学习笔记162:开发一个多界面的应用程序之两种意图
    Java基础知识强化19:Java中switch分支语句
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9827253.html
Copyright © 2011-2022 走看看