11.14vijos任務題切題記

五道題目:
vijos1601 保衛峯會
vijos1639 機密文件
vijos1656 萌萌趕考
vijos1710 Mrw的工資計劃
vijos1764 Dual Matrices

題解時間

vijos1601 保衛峯會

地址:https://vijos.org/p/1601

背景

在北約峯會期間,必須使用許多保鏢保衛北約組織的各國代表。代表們除了由他自己的隨身保鏢保護外,組委會還指派了一些其他的特工和阻擊手保護他們。

描述

爲了使他們的工作卓有成效,使被保衛的人的安全儘可能得到保障,保鏢被分配到被保護人的各個方向。

保鏢的最佳站立位置應該是這樣的:被保護人應站在所有保鏢的對稱中心。但是,只要被保護人一移動,保鏢就很難根據要人的新位置調整位置。大多數的特工都很難對此作出實時調整。

因此,內政部長高斯決定將該過程逆轉一下,保鏢先站好自己的位置,然後要人在他們的對稱中心找到合適的位置。如果要人隨便走動,我們就對他的安全不必負責。

作爲一個優秀的程序員,你的工作是使這個過程自動操作。給出一組N個點(保鏢的位置),你要找出它們的對稱中心S,在這兒被保護人將相對安全。下面以此類推。

首先我們給定一點A以及對稱中心S,點A’是點A以S爲對稱中心形成的像點,即點S是線段AA’的對稱中心。

點陣組(X)以S爲中心的像點是由每個點的像點組成的點陣組。X是用來產生對稱中心S的,即點陣X以S爲中心的像點的集合即爲點陣X本身。

輸入格式

輸入文件第一行是一個整數N,1<=N<=20000,接下來的N行每行包含用空格隔開的兩個整數Xi和Yi,-100000<=Xi,Yi<=100000,表示這組點陣中第I個點的笛卡爾座標值。

因爲任何兩個保鏢都不會站在同一個位置上,所以在給定的作業中,任何兩點都不相同。但注意保鏢可以站在被保護人相同的位置。

輸出格式

輸出文件僅有一行。如果給定的點陣能產生一個對稱中心,則輸出“V.I.P. should stay at (x,y)”,其中X和Y代表中心的笛卡爾座標值,格式爲四捨五入保留至小數點後一位。如果該組點陣無對稱中心,輸出”This is a dangerous situation!”,注意輸出時除了兩個單詞之間用一個空格隔開外,不要輸出多餘空格。

樣例輸入

8
1 10
3 6
6 8
6 2
3 -4
1 0
-2 -2
-2 4

樣例輸出

V.I.P. should stay at (2.0,3.0).

限制

每個測點1s

提示

感謝car大牛對本題的支持!

來源

由省隊訓練模擬題改編。感謝car大牛爲本題生成全新數據!

做法

尋找對稱中心,只要把橫座標和縱座標分別sort一遍,然後頭尾求平均值,如果每一組頭尾平均值都一樣,說明存在對稱中心,平均值就是答案。

vijos就是個坑!!!題目裏面的
“V.I.P. should stay at (2.0,3.0).”V.I.P後少了個點。
題目裏面是“This is a dangerous situation.”WA了無數遍之後看了題解才知道是”This is a dangerous situation!”

這裏寫圖片描述

代碼如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
typedef double DB;
const int M=20010;
const DB eps=1e-2;
int n,m,i,j,l,r;DB X,Y,tx,ty;
struct node{DB x,y;}p[M];
inline bool ok(DB x,DB y){
    if(fabs(x-y)<eps) return 1;
    return 0;
}
inline bool cmp(node aa,node bb){return aa.x<bb.x;}
inline bool CMP(node aa,node bb){return aa.y<bb.y;}
int main(){
    for(scanf("%d",&n),i=1;i<=n;i++)
        scanf("%lf%lf",&p[i].x,&p[i].y);
    for(sort(p+1,p+n+1,cmp),l=1,r=n;l<=r;l++,r--){
        if(l==1){X=(p[l].x+p[r].x)/2;continue;}
        tx=(p[l].x+p[r].x)/2;
        if(ok(X,tx)==0) return printf("This is a dangerous situation!"),0;
    }for(sort(p+1,p+n+1,CMP),l=1,r=n;l<=r;l++,r--){
        if(l==1){Y=(p[l].y+p[r].y)/2;continue;}
        ty=(p[l].y+p[r].y)/2;
        if(ok(Y,ty)==0) return printf("This is a dangerous situation!"),0;
    }return printf("V.I.P. should stay at (%.1lf,%.1lf).",X,Y),0;
}

vijos1639機密文件

地址:https://vijos.org/p/1639

描述

OI總部最近得到可靠消息,近日來怪盜基德會再次來OI總部盜竊機密文件(因爲是機密,所以不能透露= =||)。所以OIER得在怪盜基德來臨之前就把文件備份。不過,正好今天OI總部停電了(說停就停,什麼素質!),所以就得人工抄寫了#-#。現在,OI總部內一共有M份資料和K個OIER(S),需要將每一份資料都備份一份,M份資料的頁數不一定相同(有不同的,也有相同的)。現在,你作爲其中的一名OIER(當然你是不幹活的,因爲你牛!),把資料分配給OIER備份,由於人太多了(大多是無名小卒),所以每一名OIER所分配到的資料都必須是連續順序的,並且每一名OIER的備份速度是相同的。你的任務就是讓備份的時間最短,列出最短的方案,數據可能存在多個解,所以,當存在多個解時,讓前面的人少備份(先來先休息^-^)。

輸入格式

第一行有兩個整數:M,K。表示書本的數目和OIER的人數。

第二行:由M個分隔的整數構成,分別表示M本書的頁數。

(第I份資料的編號爲I)。

對於50%的數據,(1<=k<=m<=500);
對於全部的數據,(1<=k<=m<=1000)的離散隨機數據。

輸出格式

共K行:
每一行都由兩個整數。:第I行表示第I個OIER備份的資料編號的起止。

樣例輸入

8 3
1 2 3 4 5 6 7 8

樣例輸出

1 3
4 6
7 8

限制

各個測試點1s

來源

from飛過海

做法

二分答案,從後往前枚舉判斷正確性。輸出答案的時候也只要按照枚舉到的答案從後往前掃一遍把頭尾壓進棧裏再輸出就行了,記得先把n壓棧,最後1壓棧;

代碼如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int M=1010,inf=0x3f3f3f3f;
int m,k,n,i,j,l,r,tot;
int a[M],b[M<<1];
inline bool ok(int x){
    int i,cnt=0,t=0;
    for(i=m;i;i--){
        t+=a[i];
        if(t>x){
            i++,t=0,cnt++;
            if(cnt>=k) return 0;
        }
    }return 1;
}
inline void get(int x){
    int i,cnt=0,t=0;
    for(b[++tot]=i=m;i;i--){
        t+=a[i];
        if(t>x) t=0,cnt++,b[++tot]=i+1,b[++tot]=i,i++;
    }for(b[++tot]=1,i=tot;i;i-=2)
        printf("%d %d\n",b[i],b[i-1]);
}
int main(){
    for(scanf("%d%d",&m,&k),i=1;i<=m;i++) scanf("%d",a+i);
    for(l=1,r=inf;l<r-1;){
        int mid=l+r>>1;
        if(ok(mid)) r=mid;
        else l=mid;
        //cout<<l<<" "<<r<<endl;
    }if(ok(l)) get(l);
    else get(r);
    //for(i=1;i<=tot;i++) printf("%d: %d\n",i,b[i]);
    return 0;
}

vijos1656 萌萌趕考

地址:https://vijos.org/p/1656

描述

綿羊爸爸一晚做了一個奇怪的夢,他夢見了萌萌十七歲的時候參加高考。萌萌所在的考點十分奇特,只有在規定的那1秒鐘時刻纔會開放(也就是說恰好到達考點,超過或時間未到都不能進入考點)。而萌萌從家裏(萌萌的家在左上角)出去,在參加考試的途中可以在大街上走走(可以往上下左右任意方向走,不可以重複經過同一區域),但不能去娛樂場所。現在給你一張JS市的地圖,以及從萌萌離開家到考點開放的時間,請你預測萌萌在綿羊老師的夢中能否成功參加這次神奇的高考?

輸入格式

輸入數據包含多個測試點(不超過5個)。

每個測試點的第一行包含三個正整數N,M,Time(0 < N,M < 7; 0 < Time < 50)。接下來N行給出從萌萌家到考點的地圖,每行包含M個字符。所有字符中僅會出現以下情況:
‘*’:表示普通道路;
‘D’:表示當地的考點(僅會出現一次);
‘H’:表示娛樂場所;
左上角的方格內字符一定爲’*’。注意:出發點一開始不算走過。

文件將以0 0 0作爲結束。

輸出格式

對於每一個測試點,你只需要輸出’Yes’表示可以準時到達,反之則輸出’No’。

樣例輸入

4 3 4
S**
* H *
* H D
* H *
3 5 5
S* H * *
H * * * *
D * * * *
0 0 0

樣例輸出

Yes
No

來源

2009年江中信奧模擬賽

做法

暴力dfs,圖小的可憐,加
點剪枝,不然就T了。。。。

%%%ZHZXliteng

論如何讓一道題跑出2234ms和3
1ms的時間

代碼如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define C(a) memset(a,0,sizeof a)
using namespace std;
const int M=10;
char a[M][M],v[M][M];
int n,m,i,j,T,f;
inline void dfs(int x,int y,int t){
    if(f) return;
    if(t>T) return;
    if(a[x][y]=='D'){if(t==T) f=1;return;}
    //if(x==1&&y==1) t=0;
    //printf("x:%d y:%d t:%d\n",x,y,t);
    if(!v[x+1][y]&&x+1<=n&&a[x+1][y]!='H') v[x+1][y]=1,dfs(x+1,y,t+1),v[x+1][y]=0;
    if(!v[x][y+1]&&y+1<=m&&a[x][y+1]!='H') v[x][y+1]=1,dfs(x,y+1,t+1),v[x][y+1]=0;
    if(!v[x-1][y]&&x-1>=1&&a[x-1][y]!='H') v[x-1][y]=1,dfs(x-1,y,t+1),v[x-1][y]=0;
    if(!v[x][y-1]&&y-1>=1&&a[x][y-1]!='H') v[x][y-1]=1,dfs(x,y-1,t+1),v[x][y-1]=0;
}
int main(){
    for(;(~scanf("%d%d%d",&n,&m,&T))&&n!=0;){
        for(C(a),C(v),f=0,i=1;i<=n;i++) scanf("%s",a[i]+1);
        dfs(1,1,0);if(f) puts("Yes");
        else puts("No");
    }return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章