2014年百度之星程序設計大賽 - 資格賽 (未完成)

                   鏈接

    第一次 看到題目的時候,我還以爲,這套題目好簡單,可是當我做下去的時候,發現是我想的太簡單了、、

     沒做完,這幾天補上、、

Energy Conversion

Problem Description
  魔法師百小度也有遇到難題的時候——
  現在,百小度正在一個古老的石門面前,石門上有一段古老的魔法文字,讀懂這種魔法文字需要耗費大量的能量和大量的腦力。
  過了許久,百小度終於讀懂魔法文字的含義:石門裏面有一個石盤,魔法師需要通過魔法將這個石盤旋轉X度,以使上面的刻紋與天相對應,才能打開石門。
  但是,旋轉石盤需要N點能量值,而爲了解讀密文,百小度的能量值只剩M點了!破壞石門是不可能的,因爲那將需要更多的能量。不過,幸運的是,作爲魔法師的百小度可以耗費V點能量,使得自己的能量變爲現在剩餘能量的K倍(魔法師的世界你永遠不懂,誰也不知道他是怎麼做到的)。比如,現在百小度有A點能量,那麼他可以使自己的能量變爲(A-V)*K點(能量在任何時候都不可以爲負,即:如果A小於V的話,就不能夠執行轉換)。
  然而,在解讀密文的過程中,百小度預支了他的智商,所以他現在不知道自己是否能夠旋轉石盤,打開石門,你能幫幫他嗎?

Input
  輸入數據第一行是一個整數T,表示包含T組測試樣例;
  接下來是T行數據,每行有4個自然數N,M,V,K(字符含義見題目描述);
  數據範圍:
  T<=100
  N,M,V,K <= 10^8
Output
  對於每組數據,請輸出最少做幾次能量轉換才能夠有足夠的能量點開門;
  如果無法做到,請直接輸出-1。

Sample Input
4 10 3 1 2 10 2 1 2 10 9 7 3 10 10 10000 0

Sample Output
3 -1 -1 0
 
    其實我一開始做到這題的時候,就直接用bfs 了,因爲標記數組,就直接MLE 了,233、

    這個不同於那種先怎樣,再怎樣,可能存在不同的更好的解,因爲這個如果不能變大的話,就不可能達到要求,所以只要無腦公式,看是否變大就可以了、

   

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

int main()
{
    int t;
    int n, v, k;
    long long int m;
    while(~scanf("%d",&t))
    {
        while(t --)
        {
            scanf("%d%lld%d%d",&n,&m,&v,&k);
            int step = 0;
            long long int  pre = m;
            while(m < n)
            {
                if(m > v)
                    m = (m - v)*k;
                else
                {
                    step = -1;
                    break;
                }
                if(m <= pre)
                {
                    step = -1;
                    break;
                }
                pre = m;
                step ++;
            }
            printf("%d\n", step);
        }
    }
}


Disk Schedule


Problem Description
有很多從磁盤讀取數據的需求,包括順序讀取、隨機讀取。爲了提高效率,需要人爲安排磁盤讀取。然而,在現實中,這種做法很複雜。我們考慮一個相對簡單的場景。
磁盤有許多軌道,每個軌道有許多扇區,用於存儲數據。當我們想在特定扇區來讀取數據時,磁頭需要跳轉到特定的軌道、具體扇區進行讀取操作。爲了簡單,我們假設磁頭可以在某個軌道順時針或逆時針勻速旋轉,旋轉一週的時間是360個單位時間。磁頭也可以隨意移動到某個軌道進行讀取,每跳轉到一個相鄰軌道的時間爲400個單位時間,跳轉前後磁頭所在扇區位置不變。一次讀取數據的時間爲10個單位時間,讀取前後磁頭所在的扇區位置不變。磁頭同時只能做一件事:跳轉軌道,旋轉或讀取。
現在,需要在磁盤讀取一組數據,假設每個軌道至多有一個讀取請求,這個讀取的扇區是軌道上分佈在 0到359內的一個整數點扇區,即軌道的某個360等分點。磁頭的起始點在0軌道0扇區,此時沒有數據讀取。在完成所有讀取後,磁頭需要回到0軌道0扇區的始點位置。請問完成給定的讀取所需的最小時間。
Input
輸入的第一行包含一個整數M(0<M<=100),表示測試數據的組數。
對於每組測試數據,第一行包含一個整數N(0<N<=1000),表示要讀取的數據的數量。之後每行包含兩個整數T和S(0<T<=1000,0<= S<360),表示每個數據的磁道和扇區,磁道是按升序排列,並且沒有重複。
Output
對於每組測試數據,輸出一個整數,表示完成全部讀取所需的時間。
Sample Input
3 1 1 10 3 1 20 3 30 5 10 2 1 10 2 11
 
Sample Output
830 4090 1642

    這題一開始,我以爲是普通的模擬題,敲完樣例對的,但是提交卻是錯的,後來百度了之後才發現是什麼雙調歐幾里德旅行商問題,好高級的樣子、、、

  

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

#define INF 1 <<29

int dp[110][110];
int dis[110][110];

struct node
{
    int x;
    int y;
}point[1010];

int getdis(node a, node b)
{
    int dis_1 = abs(b.y - a.y);
    int dis_2 = abs(360 - b.y + a.y);
    return min(dis_1, dis_2) + abs(a.x - b.x) * 400;
}

int main()
{
    int t, n;
    while(~scanf("%d",&t))
    {
        while(t --)
        {
            memset(dp, 0, sizeof(dp));
            memset(dis, 0, sizeof(dis));
            int ans = INF;
            scanf("%d",&n);
            for(int i = 2; i <= n + 1; i ++)
            {
                scanf("%d%d",&point[i].x,&point[i].y);
            }
            point[1].x = point[1].y = 0;
            for(int i = 1; i <= n + 1; i ++)
            {
                for(int j = 1; j <= n + 1; j ++)
                {
                    dis[i][j] = getdis(point[i], point[j]);
                    dp[i][j] = INF;
                }
            }

            dp[2][1] = dis[2][1];
            for(int i = 2; i <= n + 1; i ++)
            {
                for(int j = 1; j < i; j ++)
                {
                    dp[i][j] = min(dp[i][j], dp[i - 1][j] + dis[i - 1][i]);
                    dp[i][i - 1] = min(dp[i][i - 1],dp[i - 1][j] + dis[j][i]);
                }
            }

            for(int i = 1; i < n + 1; i ++)
            {
                int s = dis[i][n];
                if(ans > dp[n][i] + s)
                    ans = dp[n][i] + s;
            }

            printf("%d\n",ans + n*10);
        }
    }
}

Labyrinth

Problem Description
度度熊是一隻喜歡探險的熊,一次偶然落進了一個m*n矩陣的迷宮,該迷宮只能從矩陣左上角第一個方格開始走,只有走到右上角的第一個格子纔算走出迷宮,每一次只能走一格,且只能向上向下向右走以前沒有走過的格子,每一個格子中都有一些金幣(或正或負,有可能遇到強盜攔路搶劫,度度熊身上金幣可以爲負,需要給強盜寫欠條),度度熊剛開始時身上金幣數爲0,問度度熊走出迷宮時候身上最多有多少金幣?
Input
輸入的第一行是一個整數T(T < 200),表示共有T組數據。
每組數據的第一行輸入兩個正整數m,n(m<=100,n<=100)。接下來的m行,每行n個整數,分別代表相應格子中能得到金幣的數量,每個整數都大於等於-100且小於等於100。
Output
對於每組數據,首先需要輸出單獨一行”Case #?:”,其中問號處應填入當前的數據組數,組數從1開始計算。
每組測試數據輸出一行,輸出一個整數,代表根據最優的打法,你走到右上角時可以獲得的最大金幣數目。
Sample Input
2 3 4 1 -1 1 0 2 -2 4 2 3 5 1 -90 2 2 1 1 1 1

Sample Output
Case #1: 18 Case #2: 4

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章