Codeforces Round #683 (Div. 2, by Meet IT)(A->C)(构造,思维,贪心)

A:http://codeforces.com/contest/1447/problem/A

解析:

直接输出n个数,1~n即可。

#include<iostream>
#include<cstdio>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        cout<<n<<endl;
        for(int i=1;i<=n;i++)
            cout<<i<<" ";
        cout<<endl;
    }
}

B:http://codeforces.com/contest/1447/problem/B

题意:

操作:找一组相邻格子,里面的数都乘-1

求矩阵最大和,操作数不限。

解析:

对于-1,应该有这种思维:一个数乘两次-1,不变。

举个例子,我想改变-1:

-1 2

3  4

-1,2乘-1,那么有:

1  -2

3  4

-2,4乘-1,那么有:

1  2

3  -4

可以发现,要改变一个数,只需要在矩阵的任意一个位置找一个数和它一起乘-1即可,不一定需要相邻。因为相邻的话,经过层层转嫁,可以把影响换到任意一个位置。

根据贪心,我们要改变的,就是负数。

把<=0的全收集起来,排个序,数目记为cnt。因为每次要改变一对数,所以如果cnt是偶数的话,里面的数全可以变成正数。

cnt为奇数的话,奇数-1是偶数,把偶数部分变正,那么此时还剩最后一个负数,改变它是有可能增加总体和的,所以把正数那边的最小值找到,和这个负数的绝对值比较一下,看一下是否能增加总体和。

#include<iostream>
#include<cstdio>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=111;
int a[maxn][maxn];
int b[maxn];
const int minn=999999;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        int m;
        cin>>n>>m;
        int sum=0;
        int minx=minn;
        int all=0,tot=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];        
                if(a[i][j]>0)
                    all+=a[i][j];
                else
                    b[tot++]=a[i][j];        
            }
        sort(b,b+tot);
        if(tot%2==0)
        {
            for(int i=tot-1;i>=0;i--)
                sum+=fabs(b[i]);
        }
        else
        {
            int maxx=-minn;
            for(int i=0;i<tot-1;i++)
                sum+=fabs(b[i]);
            int ok=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(a[i][j]>0&&a[i][j]<minx)
                    {
                        minx=min(minx,a[i][j]);
                        ok=1;
                    }
                }
            }
            if(!ok)
            {
                sum+=b[tot-1];
            }            
            else if(fabs(b[tot-1])>minx)
            {
                
                sum+=fabs(b[tot-1]);
                all-=2*minx;//这里要注意
            //    cout<<all<<endl;
            }
            else
            {
                sum+=b[tot-1];
            }
        }
        cout<<sum+all<<endl;
    }
}
//33
//2 2
//3 4
//-5 1

C:http://codeforces.com/contest/1447/problem/C

题意:

给出n个小包,每个包含wi个。给出总容量W,

能否用一些小包,使得它们的容量>=W/2&&<=W

解析:

把<=W的收集起来。

从大到小排序,从大往小贪心即可。

不能从小到大贪心,比如:

3  11

2  3  7

从小的话,无解,但是从大的话就有解。

#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=2e5+10,maxn2=31*maxn;
int b[maxn];
int tot=0;
struct node
{
    ll val;
    int id;
}st[maxn];
bool cmp(node a,node b)
{
    return a.val>b.val;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,tot=0;
        ll w;
        cin>>n>>w;
        for(int i=1;i<=n;i++)
        {
            ll x;
            cin>>x;
            if(x<=w)
            {
                tot++;
                st[tot].val=x;
                st[tot].id=i;
            }
        }
        sort(st+1,st+1+tot,cmp);
        ll sum=0;
        int tot2=0;
        for(int i=1;i<=tot;i++)
        {
            if(sum+st[i].val>w)
                continue;
            sum+=st[i].val;
            b[tot2++]=st[i].id;
        }
        sort(b,b+tot2);
        if(sum*2<w)
            cout<<"-1"<<endl;
        else
        {
            cout<<tot2<<endl;
            for(int i=0;i<tot2;i++)
                cout<<b[i]<<" ";
            cout<<endl;
        }
    }
    return 0;
}

 

posted @ 2020-11-16 20:52  liyexin  阅读(103)  评论(0)    收藏  举报