UOJ Logo heqingyu的博客

博客

Week 6总结

2018-04-15 19:57:09 By heqingyu

这周终于上300分了。。然而其实400是挺稳的。。。

犯了一些玄学错误(递归爆栈,搜索变贪心。。。。)

本来预计得分是100+100+100+100+30+10=440的。。。@Siyuan最强啦

T1:

洛谷原题,USACO的佬(没有打错)题了。。。

枚举最小山峰的高度,然后把所有山都修建成符合条件的区间内的山即可

code:

#include<bits/stdc++.h>
using namespace std;
int n,a[1010];
int ans=1e9,cnt;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int h=0;h<=100;h++){
        cnt=0;
        for(int i=1;i<=n;i++){
            if(a[i]>h) cnt+=(a[i]-h)*(a[i]-h);
            if(a[i]<h-17) cnt+=(h-17-a[i])*(h-17-a[i]);
        }
        ans=min(ans,cnt);
    }
    printf("%d",ans);
    return 0;
}

T2:

洛谷原题,USACO佬题(还是没有打错。。)。。。

首先考虑模拟,然后把时间和距离分开来处理就好了呀。。。

code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;  
char ch;  
double last,ans;
int d[10010],t[10010];  
int n,x,now=1;
int nt,nd,cnt=1;  
int main(){  
    d[++nd]=0;  
    d[++nd]=1000;  
    scanf("%d",&n);  
    for(int i=1;i<=n;i++){  
        getchar();    
        scanf("%c%d",&ch,&x);  
        if(ch=='T') t[++nt]=x;  
        else d[++nd]=x;  
    }  
    sort(d+1,d+nd+1);  
    sort(t+1,t+nt+1);  
    for(int i=1;i<nd;i++){  
        last=d[i];  
        while(last<d[i+1]&&now<=nt&&ans+(d[i+1]-last)*cnt>t[now]){  
            last+=(t[now]-ans)/cnt;  
            cnt++;  
            ans=t[now++];  
        }  
        ans+=(d[i+1]-last)*cnt;  
        cnt++;  
    }  
    printf("%.0lf\n",ans);  
    return 0;
}

T3:

4^12次的爆搜,然而我却忘记了每组都要3头牛。。。

后来想起来,但是想到这样会导致答案不优,就懒得改了。。。(woc懒癌晚期了。。)

然而发现这样是错的。。。

code:

#include<bits/stdc++.h>
using namespace std;
int b[5],a[20];
int ans=1e9;
void dfs(int dep,int cnt1,int cnt2,int cnt3,int cnt4){
    if(dep>12){
        ans=min(ans,max(max(cnt1,cnt2),max(cnt3,cnt4))-min(min(cnt1,cnt2),min(cnt3,cnt4)));
        return;
    }
    if(b[1]<3){
        b[1]++;
        dfs(dep+1,cnt1+a[dep],cnt2,cnt3,cnt4);
        b[1]--;
    }
    if(b[2]<3){
        b[2]++;
        dfs(dep+1,cnt1,cnt2+a[dep],cnt3,cnt4);
        b[2]--;
    }
    if(b[3]<3){
        b[3]++;
        dfs(dep+1,cnt1,cnt2,cnt3+a[dep],cnt4);
        b[3]--;
    }
    if(b[4]<3){
        b[4]++;
        dfs(dep+1,cnt1,cnt2,cnt3,cnt4+a[dep]);
        b[4]--;
    }
    return;
}
int main(){
    for(int i=1;i<=12;i++)scanf("%d",&a[i]);
    dfs(1,0,0,0,0);
    printf("%d",ans);
    return 0;
}

T4:

一开始想到最小生成树。。。然后赛后验证发现爆零。。(还好没有写。。)

想到了二分+DFS来判断最小答案。。。

然而痛苦地爆栈我也很绝望。。。。(早知道写queue的广搜了。。。)

code:

#include<bits/stdc++.h>
#define pii pair<int,int> 
#define fi first
#define se second
#define pb push_back
#define mk make_pair
using namespace std;
int m,n,ans,tot,vis[510][510];
vector<pii > mp;
int h[510][510],x,t;
void dfs(int x,int y,int tot){
    if(x<1||x>n||y<1||y>m) return;
    if(vis[x][y]) return;
    vis[x][y]=1;
    if(abs(h[x-1][y]-h[x][y])<=tot) dfs(x-1,y,tot);
    if(abs(h[x+1][y]-h[x][y])<=tot) dfs(x+1,y,tot);
    if(abs(h[x][y-1]-h[x][y])<=tot) dfs(x,y-1,tot);
    if(abs(h[x][y+1]-h[x][y])<=tot) dfs(x,y+1,tot);
    return;
}
bool check(int d){
    dfs(mp[0].fi,mp[0].se,d);
    bool flag=true;
    for(int i=0;i<mp.size();i++)if(!vis[mp[i].fi][mp[i].se]) flag=false;
    return flag;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&h[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&x);
            if(x==1) mp.pb(mk(i,j));
        }
    int l=0,r=1e9;
    while(l<=r){
        int mid=l+r>>1;
        memset(vis,0,sizeof(vis));
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

T5:

这题的线段树+扫描线实在是太♂骚了。。。。

于是只打了个n^3的暴力,骗了30分。。。。

code:

#include<bits/stdc++.h>
using namespace std;
int mp[1010][1010];
int n,a,x,b,y;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&x,&y,&a,&b);
        x+=200;
        y+=200; 
        for(int j=x;j<=x+a-1;j++)
            for(int ij=y;ij<=y+b-1;ij++)
                mp[j][ij]=1;
    }
    int ans=0;
    for(int i=0;i<=1000;i++)
        for(int j=0;j<=1000;j++)
            ans+=mp[i][j];
    printf("%d",ans);
    return 0;
}

T6:

这题标算很♂玄学。。。

于是打了个@Siyuan教我的骗分

就是输出样例和10.。。。(样例特判。。)

竟然能拿40分!!!太神了!!!比暴力还高!!!!

code:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
    scanf("%d%d",&n,&m);
    if(n==3&&m==6) puts("3");
    else puts("10");
    return 0;
}

评论

暂无评论