zoukankan      html  css  js  c++  java
  • Codeforces Round #601 (Div. 2)补题

    A.Changing Volume

    题意:给你a,b两个数,然后你可以通过 -1,-2,-5,+1,+2,+5来调节a的大小使之达到b,但是在a减小的过程中不能小于0. 如果无法成功输出-1,否则输出最少调节的次数

    思路:贪心,类似拿硬币或者放物品,先装大的,然后再塞小的。

        #include <bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        int main(){
            int T;
            cin>>T;
            while(T--){
                int a,b;
                cin>>a>>b;
                if(a==b){
                    cout<<0<<endl;
                }else{
                    if(a>b) swap(a,b);
                    int cont = 0;
                    while(a!=b){
                        if((b-a)/5>0) {
                            cont+=(b-a)/5;
                            b -= 5*((b-a)/5);
                                
                        }else if((b-a)/2>0&&(b-a)/5==0){
                            cont += (b-a)/2;
                            b -= 2*((b-a)/2);
                            
                        }else if(b-a==1){
                            cont++;
                            b -= 1;    
                        }
                    }    
                    cout<<cont<<endl;
                }
                
            }
            
        } 
    View Code

    B. Fridge Lockers

    题意:给你n个冰箱,且给出他们的重量 wi ,把两个不同的冰箱用一条铁链连接起来的花费为 wi+ wj ;任意两个冰箱之间能够连接多条铁链,现在给出你需要连接的铁链个数。最后需要满足每个冰箱上至少有两条铁链,求最后连完的最小花费。如果最后冰箱不能满足有两条铁链,则输出-1.

    思路:首先,要把所有冰箱两两连接起来,就是连接成一个环,这样花费是最小的,也就是 2 * ∑ wi , 然后对剩余没有连接的铁链就贪心连接最小的两个重量冰箱就行

        #include<bits/stdc++.h>
        using namespace std;
        int T;
        vector<pair<int,int> >ans;
        long long cost[1010];
        int main(){
            scanf("%d",&T);
            while(T--){
                ans.clear();
                int n,m;scanf("%d %d",&n,&m);
                for(int i = 1;i <= n;i++) scanf("%lld",&cost[i]);
                if( m != n || n == 2) puts("-1");
                else {
                    long long ans1 = 0;
                    for(int i = 1;i < n;i++) {
                            ans.push_back(make_pair(i,i + 1));
                            ans1 += cost[i + 1] + cost[i];
                    }
                    ans.push_back(make_pair(n,1));
                    ans1 += cost[n] + cost[1];
                    printf("%lld
    ",ans1);
                    for(auto it : ans) printf("%d %d
    ",it.first,it.second);
                }
            }
        }
    View Code

    C. League of Leesins

    题意:一个长为n的序列,序列中的数值为从 1~n,且随机。现在把它(类似长度为 3 的滑动窗口),从左往右 截取得到 n-2个序列断,你可以随机将它打乱,无论是窗口里面的数值位置, 或者是滑动窗口(截取序列端)的位置。现在 给出n-2个序列端,你要输出符合条件的原序列,任意满足均可

    思路:

    (1)一开始的想法是按照图的方法,把每个序列段抽象成一个点,然后如果有两个序列段有两个公共的值的话,就连接一条边。最后会发现,处于左右端的序列段连接边数为1.然后再找到与之相连的序列端,确定第一个序列的顺序,之后就可以确定整个序列的位置。 然后把前三个序列端的值放入multiset中统计个数,出现次数为1的在左右两端,出现次数为3的在中间,这样就确定号顺序了。

    (2)直接将每一个序列段中的点连接起来,边数为1的即为左右端点,然后如果下一个点的连边数为2则必然为下一个位置。用vis来记录已经访问的值,最后不断往后搜索边,输出整个序列。

        #include<bits/stdc++.h>
        #define ll long long
        using namespace std;
        const int MAXN=1e5+10;
        vector<int>v[MAXN];
        map<int,int>mp;
        int vis[MAXN];
        int main()
        {
            int n;
            cin>>n;
            for(int i=1;i<=n-2;i++)
            {
                int x,y,z;
                cin>>x>>y>>z;
                //将在同一组的点连接起来
                v[x].push_back(y);
                v[x].push_back(z);
         
                v[y].push_back(x);
                v[y].push_back(z);
         
                v[z].push_back(y);
                v[z].push_back(x);
                mp[x]++,mp[y]++,mp[z]++;
            }
            int x,y;
            for(int i=1;i<=n;i++)
            {
                //个数为1的只能为端点
                if(mp[i]==1)
                {
                    x=i;
                    break;
                }
            }
            //等于2的点为下一个排序
            if(mp[v[x][0]]==2)
            {
                y=v[x][0];
            }
            else
                y=v[x][1];
            vis[x]=vis[y]=1;
            cout<<x<<" "<<y<<" ";
            for(int i=1;i<=n-2;i++)
            {
                int z;
                for(int j=0;j<v[x].size();j++)
                {
                    if(!vis[v[x][j]])
                    {
                        z=v[x][j];
                        break;
                    }
                }
                vis[z]=1;
                cout<<z<<" ";
                x=y,y=z;
            }
            cout<<endl;
            return 0;
        }
    View Code

    D. Feeding Chicken

    题意:给你一张图 n x m ,图上的R代表 rice/米 ,. 代表空地,现在给你k只鸡(最多六十二只,输出时用"a-z,A-Z,0-9"来表示,然后让你给鸡分配地盘,使得(1)每个地盘的格子必须连接起来(即不能被隔开),同时使每只鸡吃到的食物最多的和最少的差值最小。

    思路:要使差值最小,贪心。平均分配,然后余下的分给不同的鸡。连接:相当于一笔画,把整个图一笔画搜索,可以按照 S 型。

        #include<bits/stdc++.h>
        #define ll long long
        using namespace std;
        const int MAXN=1e5+10;
        string gph[500];
        vector<char>s;
        void init(){
            for(int i=0;i<26;i++){
                s.push_back('A'+i);
            }
            for(int i=0;i<26;i++){
                s.push_back('a'+i);
            }
            for(int i=0;i<10;i++){
                s.push_back('0'+i);
            }
         
         
        }
        char ans[500][500];
        int main(){
            int T;
            cin>>T;
            init();
            while(T--){
                memset(ans,0,sizeof(ans));
                int n,m,k;
                cin>>n>>m>>k;
                for(int i=0;i<n;i++){
                    cin>>gph[i];
                }
                int cont = 0;
                for(int i=0;i<n;i++){
                    for(int j=0;j<m;j++)
                    if(gph[i][j]=='R') cont++;
                }
                int res = cont % k ;//多出的个数
                int turn = cont / k;//每一只鸡吃的最少粮食
                int top = 0;//标号
                //S形填数
                int t = 0;
                int x = 0,y = 0;
                int cnt = 0;
                int limit = turn + 1;
                memset(ans,0,sizeof(0));
                for(int i=0;i<n;i++){
                    if(i%2==0){
                        for(int j=0;j<m;j++){
                            if(gph[i][j]=='R') cnt++;
                            if(cnt>=limit&&res>0) {cnt = 0; res--; top++;}
                            if(cnt>=limit&&res<=0) {cnt = 0; top++; limit = turn;}
                            ans[i][j] = s[top];
                        }
         
                    }else{
                        for(int j=m-1;j>=0;j--){
                            if(gph[i][j]=='R') cnt++;
                            if(cnt>=limit&&res>0) {cnt = 0; res--; top++;}
                            if(cnt>=limit&&res<=0) {cnt = 0; top++; limit = turn;}
                            ans[i][j] = s[top];
                        }
         
                    }
         
                }
                for(int i=0;i<n;i++){
                    cout<<ans[i]<<endl;
                }
         
            }
        }
    View Code
  • 相关阅读:
    Java 简单算法--打印乘法口诀(只使用一次循环)
    Java简单算法--求100以内素数
    ubuntu 16.04 chrome flash player 过期
    java 网络API访问 web 站点
    java scoket (UDP通信模型)简易聊天室
    leetcode1105 Filling Bookcase Shelves
    leetcode1140 Stone Game II
    leetcode1186 Maximum Subarray Sum with One Deletion
    leetcode31 Next Permutation
    leetcode834 Sum of Distances in Tree
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11922072.html
Copyright © 2011-2022 走看看