2019牛客暑假多校训练营(第六场)

J:https://ac.nowcoder.com/acm/contest/886/J

1.统一类型全int或ll;2.多用min max函数,如果不需要记录位置;3.考虑边界问题,0或最后

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1010;
const ll INF=1e18+5;
ll n,m,x,sum[maxn][maxn];
ll d[maxn],f[maxn][maxn];
int main()
{
    int T,ca=0;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        memset(sum,0,sizeof(sum));
        for(ll i=1;i<=n;i++){
            for(ll j=1;j<=m;j++){
                scanf("%lld",&x);
                sum[i][j]=sum[i][j-1]-x;
            }
        }
        for(ll i=1;i<=n;i++){
            for(ll j=m;j>=0;j--){
                if(j==m) f[i][j]=sum[i][j];
                else f[i][j]=max(f[i][j+1],sum[i][j]);
            }
        }
        d[0]=0;
        for(ll i=1;i<=m;i++){
            scanf("%lld",&x);
            d[i]=d[i-1]+x;
        }
        ll ans=0,now,mx;
        bool flag;
        for(ll i=0;i<=m;i++){
            mx=INF;
            now=d[i];
            for(ll j=1;j<=n;j++){
                ll rr=f[j][i];
                now+=rr;
                mx=min(mx,rr-sum[j][i]);
            }
            ans=max(ans,now-mx);
        }
        printf("Case #%d: %lld\n",++ca,ans);
    }
    return 0;
}

B:https://ac.nowcoder.com/acm/contest/886/B

128位 转子网掩码,每16位弄成4位16进制表示,去了前导0,判断变大于等于2个0的时候,暴力模拟即可!

不能懒,自己分析清题意好好写。

1.字符串使用前一定要初始化为空;2. 0:0在最前面和最后面特殊考虑。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> p;
vector<p> vc;
string s,ss[10];
vector<char> v[10];
char m[20]={"0123456789abcdef"};
int main()
{
    int t,cc=0;
    cin>>t;
    while(t--){
        cin>>s;
        for(int i=0;i<8;i++) v[i].clear();
        vc.clear();
        int i=0,x=0;
        while(i<128){
            x=x*2+s[i]-'0';
            if((i+1)%4==0){
                v[i/16].push_back(m[x]);x=0;
            }
            i++;
        }
        for(int i=0;i<8;i++){
            int j=0;ss[i]="";
            while(j<4&&v[i][j]=='0') j++;
            if(j==4) ss[i]="0";
            else{
                for(int k=j;k<4;k++) ss[i]+=v[i][k];
            }
        }
        int l=-1,r=-1;
        for(int i=0;i<8;i++){
            if(l==-1&&ss[i]=="0"){
                l=i;
            }
            else if(l!=-1&&ss[i]=="0"){
                r=i;
            }
            else if(ss[i]!="0"){
                if(l!=-1&&r!=-1) vc.push_back(p(l,r));
                l=-1;r=-1;
            }
            //cout<<l<<" "<<r<<endl;
        }
        if(l!=-1&&r!=-1) vc.push_back(p(l,r));
        string ans="",temp;
        for(int i=0;i<8;i++){
            ans+=ss[i];
            if(i!=7) ans+=':';
        }
        int dui=vc.size();
        //cout<<dui<<endl;
        for(int i=0;i<dui;i++){
            temp="";
            int ll=vc[i].first,rr=vc[i].second;
            for(int j=0;j<ll;j++){
                 temp+=ss[j];
                 if(j!=ll-1) temp+=":";
            }
            temp+="::";
            for(int j=rr+1;j<8;j++){
                temp+=ss[j];
                if(j!=7) temp+=":";
            }
            //cout<<temp<<endl;
            if(temp.size()<ans.size()||(temp.size()==ans.size()&&temp<ans))
                ans=temp;
        }
        cout<<"Case #"<<++cc<<": "<<ans<<endl;
    }
    return 0;
}

D:https://ac.nowcoder.com/acm/contest/886/D

给出n个物品,k个背包,求装下所有物品所需要的最小背包体积。

1.答案不具有单调性,即00100001111111,所以不能二分;2.每次判断的时候枚举每个背包,从大到小,依次尝试的放。最后判断时候所有的都放完了;3.最小体积的下界sum/k,上界sum/k+maxv。设某个最小体积 ans 装不下,那么每个箱子的剩余空间都 < maxV 此时 k * (ans - maxV + 1) <= sum(已经放下的)   则ans <= sum/k + maxV - 1。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,k,a[maxn];
bool vis[maxn];
bool judge(int x)
{
    memset(vis,false,sizeof(vis));
    for(int i=0;i<k;i++){
        int v=0;
        for(int j=0;j<n;j++){
            if(!vis[j]&&v+a[j]<=x){
                v+=a[j];
                vis[j]=true;
            }
        }
    }
    for(int i=0;i<n;i++)
        if(!vis[i]) return false;
    return true;
}
int main()
{
    int t,cc=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        int sum=0,mx=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
            mx=max(mx,a[i]);
        }
        sort(a,a+n,greater<int>() );
        int l=sum/k,r=l+mx;
        for(int i=l;i<=r;i++){
            if(judge(i)){
                printf("Case #%d: %d\n",++cc,i);
                break;
            }
        }
    }
    return 0;
}

G:https://ac.nowcoder.com/acm/contest/886/G

蔡勒公式:判断得到星期几

1.0-9全排列,对应ABCDEFGHI表示数字,挨个判断每个日期是否满足。

2.

w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六

c:世纪(注:一般情况下,在公式中取值为已经过的世纪数,也就是年份除以一百的结果,而非正在进行的世纪,也就是现在常用的年份除以一百加一;不过如果年份是公元前的年份且非整百数的话,c应该等于所在世纪的编号,如公元前253年,是公元前3世纪,c就等于-3)

y:年(一般情况下是后两位数,如果是公元前的年份且非整百数,y应该等于cMOD100+100)

m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)

d:日

[ ]代表取整,即只要整数部分。取余完如果是负数,记得加7。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int p[15];
int month[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
string s[maxn];
bool check(int x)
{
    int y=p[(s[x][0]-'A')]*1000+p[(s[x][1]-'A')]*100+p[(s[x][2]-'A')]*10+p[(s[x][3]-'A')];
    int m=p[(s[x][5]-'A')]*10+p[(s[x][6]-'A')];
    int d=p[(s[x][8]-'A')]*10+p[(s[x][9]-'A')];
    if(y%4==0&&(y%100!=0||y%400==0)) month[2]=29;
    if(y<1600||y>9999||m<1||m>12||d<1||d>month[m])
        return false;
    if(m==1||m==2) {
        y--;
        m+=12;
    }
    int c=y/100;y=y%100;
    int w=(c/4-2*c+y+y/4+(13*(m+1))/5+d-1)%7;
    if(w<0) w=(w+7)%7;
    //int w=(d+2*m+3*(m+1)/5+y+(y/4)-(y/100)+(y/400)+1)%7;
    if(w==5) return true;
    else  return false;
}
int main() 
{
    int T,n;
    scanf("%d",&T);
    for(int ii=1;ii<=T;ii++) {
        for(int i=0;i<10;i++)
            p[i]=i;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>s[i];
        sort(s+1,s+1+n);
        n=unique(s+1,s+1+n)-s-1;
        int flag;
        do{
            flag=1;
            for(int i=1;flag&&i<=n;i++)
                if(!check(i)){
                    flag=0;break;
                }
            if(flag) break;
        }while(next_permutation(p,p+10));
        printf("Case #%d: ",ii);
        if(flag==0) puts("Impossible");
        else {
            for(int i=0;i<10;i++) cout<<p[i];
            cout<<endl;
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值