第一次 看到題目的時候,我還以爲,這套題目好簡單,可是當我做下去的時候,發現是我想的太簡單了、、
沒做完,這幾天補上、、
Energy Conversion
現在,百小度正在一個古老的石門面前,石門上有一段古老的魔法文字,讀懂這種魔法文字需要耗費大量的能量和大量的腦力。
過了許久,百小度終於讀懂魔法文字的含義:石門裏面有一個石盤,魔法師需要通過魔法將這個石盤旋轉X度,以使上面的刻紋與天相對應,才能打開石門。
但是,旋轉石盤需要N點能量值,而爲了解讀密文,百小度的能量值只剩M點了!破壞石門是不可能的,因爲那將需要更多的能量。不過,幸運的是,作爲魔法師的百小度可以耗費V點能量,使得自己的能量變爲現在剩餘能量的K倍(魔法師的世界你永遠不懂,誰也不知道他是怎麼做到的)。比如,現在百小度有A點能量,那麼他可以使自己的能量變爲(A-V)*K點(能量在任何時候都不可以爲負,即:如果A小於V的話,就不能夠執行轉換)。
然而,在解讀密文的過程中,百小度預支了他的智商,所以他現在不知道自己是否能夠旋轉石盤,打開石門,你能幫幫他嗎?
接下來是T行數據,每行有4個自然數N,M,V,K(字符含義見題目描述);
數據範圍:
T<=100
N,M,V,K <= 10^8
如果無法做到,請直接輸出-1。
這個不同於那種先怎樣,再怎樣,可能存在不同的更好的解,因爲這個如果不能變大的話,就不可能達到要求,所以只要無腦公式,看是否變大就可以了、
#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
磁盤有許多軌道,每個軌道有許多扇區,用於存儲數據。當我們想在特定扇區來讀取數據時,磁頭需要跳轉到特定的軌道、具體扇區進行讀取操作。爲了簡單,我們假設磁頭可以在某個軌道順時針或逆時針勻速旋轉,旋轉一週的時間是360個單位時間。磁頭也可以隨意移動到某個軌道進行讀取,每跳轉到一個相鄰軌道的時間爲400個單位時間,跳轉前後磁頭所在扇區位置不變。一次讀取數據的時間爲10個單位時間,讀取前後磁頭所在的扇區位置不變。磁頭同時只能做一件事:跳轉軌道,旋轉或讀取。
現在,需要在磁盤讀取一組數據,假設每個軌道至多有一個讀取請求,這個讀取的扇區是軌道上分佈在 0到359內的一個整數點扇區,即軌道的某個360等分點。磁頭的起始點在0軌道0扇區,此時沒有數據讀取。在完成所有讀取後,磁頭需要回到0軌道0扇區的始點位置。請問完成給定的讀取所需的最小時間。
對於每組測試數據,第一行包含一個整數N(0<N<=1000),表示要讀取的數據的數量。之後每行包含兩個整數T和S(0<T<=1000,0<= S<360),表示每個數據的磁道和扇區,磁道是按升序排列,並且沒有重複。
這題一開始,我以爲是普通的模擬題,敲完樣例對的,但是提交卻是錯的,後來百度了之後才發現是什麼雙調歐幾里德旅行商問題,好高級的樣子、、、
#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
每組數據的第一行輸入兩個正整數m,n(m<=100,n<=100)。接下來的m行,每行n個整數,分別代表相應格子中能得到金幣的數量,每個整數都大於等於-100且小於等於100。
每組測試數據輸出一行,輸出一個整數,代表根據最優的打法,你走到右上角時可以獲得的最大金幣數目。