1. 程式人生 > >2019/1/28測試

2019/1/28測試

== 需要 main its esp ... cor truct 最大和

考得最瓜的一次試,一個題也沒A。。

題目 A: 迷宮

題目描述

【問題描述】

電腦遊戲中有許多令人頭疼的迷宮,會花費玩家相當多的時間,你通過秘笈獲得了遊戲迷宮的地圖,你希望找到最短的一條走出迷宮的道路,並且想知道一共有多少條最短的道路,但是由於地圖非常龐大,所以你不能在短時間找出這些道路,因此,你需要編寫一個程序來找出這些最短的道路,並且統計一下一共有多少條這樣的道路。

例如,對於下圖所示的迷宮:

S

X

X

X

X

E

X表示障礙物,不可以通過,S表示迷宮的入口,E表示迷宮的出口。顯然,從入口到出口至少需要走6步,而長度為6的道路一共有兩條。

【輸入文件】

輸入文件maze.in,第一行是一個整數n(1 ≤n ≤ 25),表示迷宮是一個n×n的矩陣。以下n行每行有n個字符來描述地圖,“.”表示可以通過,“X”表示不可以通過,“S”表示迷宮的入口,“E”表示迷宮的出口。(註意:所有的字母均為大寫)。

【輸出文件】

輸出文件maze.out包括兩行,第一行包含一個整數,表示從入口到出口走的最短距離。第二行包含一個整數,表示最短路徑的條數,答案保證小於231

【樣例輸入】

4

...S

.XX.

.XX.

E...

【樣例輸出】

6

2

一個dp,然而考試是以為是搜索,還寫炸了,直接爆零(主要是字符讀入炸了,改了後還是有50分的。。

正解:用dp[i][j][k]表示第i步走到j,k的方案總數,那麽轉移方程就很簡單了,懶得寫直接看代碼

#include<bits/stdc++.h>
using namespace
std; int dirx[]={-1,1,0,0},diry[]={0,0,-1,1}; int n,dp[26*26][26][26],sx,sy,ex,ey; char mp[27][27]; int main(){ scanf("%d\n",&n); for(int i=1;i<=n;i++){ scanf("%s",mp[i]+1); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(mp[i][j]==S) sx=i,sy=j; else if(mp[i][j]==E) ex=i,ey=j; } dp[0][sx][sy]=1; for(int t=1;t<=n*n;t++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(mp[i][j]==X) continue; for(int k=0;k<4;k++){ int nx=dirx[k]+i,ny=diry[k]+j; if(nx>n||nx<1||ny>n||ny<1) continue; if(mp[nx][ny]==X) continue; dp[t][i][j]+=dp[t-1][nx][ny]; } } for(int t=1;t<=n*n;t++) { if(dp[t][ex][ey]) {printf("%d\n%d",t,dp[t][ex][ey]);return 0; } } return 0; }

題目 B: 最大數列

題目描述

【問題描述】

有一個N項的數列a1, a2 ... aN (|ai| <=10000, 1 <= i <= N)。S定義為


技術分享圖片

你的任務是求S的值,即為求一個序列的兩個不相交連續子序列的最大和。

【輸入文件】

輸入文件sequence.in的第一行是一個整數N(2 <= N <= 100000),表示數列的項數。第二行有n個整數,用空格分隔,第i個整數Ai(|Ai| <=10000)是第i位數。

【輸出文件】

輸出文件sequence.out包括一行,這一行只包含一個整數,就是S。

【樣例輸入】

5

-5 9 -5 11 20

【樣例輸出】

40

【數據規模】

對於30%的數據,保證有n <= 80;

對於70%的數據,保證有n <= 10000;

對於全部的數據,保證有n <= 100000。


這個題也是個dp,要依次枚舉斷點倒是想到了,但先預處理是真的沒考慮,打了個n^2的代碼,70fen。。

定義一個dpr[i]表示i以後的最優解,dpl[i]表示i以前的最優解,可用前綴和與後綴和來做,最後枚舉斷點,時間復雜度為O(n)

#include<bits/stdc++.h>
#define maxn 100001
using namespace std;
 
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>9||ch<0) {if(ch==-) f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) {x=x*10+ch-0;ch=getchar();}
    return x*f;
}
 
int n,a[maxn],sum1[maxn],sum2[maxn],dpl[maxn],dpr[maxn];
 
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    for(int i=1;i<=n;i++) sum1[i]=sum1[i-1]+a[i];
    for(int i=n;i>=1;i--) sum2[i]=sum2[i+1]+a[i];
    int min1=0;dpl[0]=-0x3f3f3f3f;
    for(int i=1;i<n;i++){
        dpl[i]=dpl[i-1];
        dpl[i]=max(dpl[i],sum1[i]-min1);
        min1=min(min1,sum1[i]);
    }
    int min2=0;dpr[n+1]=-0x3f3f3f3f;
    for(int i=n;i>1;i--){
        dpr[i]=dpr[i+1];
        dpr[i]=max(dpr[i],sum2[i]-min2);
        min2=min(min2,sum2[i]);
    }
    int ans=-0x3f3f3f3f;
    for(int k=1;k<n;k++)
    {
        ans=max(ans,dpl[k]+dpr[k+1]);
    }
    printf("%d",ans);
    return 0;
}

題目 C: 安裝服務器

題目描述

【問題描述】

政府計劃建立一個大型的服務器中心,為各個城市提供網絡服務。每個城市對網絡的需求量是不一樣的,而需求量越大,對線路的要求也就越高,線路的成本也就越高。因此需要選擇合適的地點修建。每個城市用一個二維整數坐標表示,兩個點之間的距離定義為水平距離+垂直距離,即a,b兩點間距離為D(a,b)=|Xa-Xb|+|Ya-Yb|。對於每個城市,線路的費用為:費用=距離×人口×城市的網絡需求程度。總的費用為各個城市的費用的總和。請你找出最適合安裝服務器(既總費用最小)的整數坐標(不一定要在城市上)。

【輸入文件】

輸入文件server.in第一行有一個正整數N(N ≤ 100000),表示城市的數量。後面的n行每行描述一個城市,每行有四個整數x,y,p,k分別表示城市的坐標,人口數,以及網絡需求程度。(0 < x, y < 2^31;p≤600, k ≤30)

【輸出文件】

輸出文件server.out包含一行。在這一行中,應當包含兩個整數x,y表示最優解的坐標,如果有多個最優解,那麽輸出x最小的,如果有x相同,那麽輸出y最小的。

【樣例輸入】

5

2 3 5 3

2 1 100 30

2 2 1 1

3 2 7 6

1 1 4 30

【樣例輸出】

2 1

【數據規模】

對於30%的數據,保證有N <= 500,x, y <= 100;

對於50%的數據,保證有N <= 5000;

對於全部的數據,保證有N <= 100000。

一個很經典的帶權中位數的題,x與y是無關的,所以只需分別算x與y的最小值就行

#include<bits/stdc++.h> #define maxn 100001 using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int n,ansx,ansy,tot; struct node{ int x,y,qz; }a[maxn]; bool cmp1(node a,node b){ return a.x<b.x; } bool cmp2(node a,node b){ return a.y<b.y; } int main(){ n=read(); for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].qz=read()*read(),tot+=a[i].qz; sort(a+1,a+1+n,cmp1); int sum=0; for(int i=1;i<=n;i++){ sum+=a[i].qz; if(sum*2>=tot){ ansx=a[i].x;break; } } sort(a+1,a+1+n,cmp2); sum=0; for(int i=1;i<=n;i++){ sum+=a[i].qz; if(sum*2>=tot){ ansy=a[i].y;break; } } printf("%d %d",ansx,ansy); return 0; }

2019/1/28測試