t094 區間運算

2021-09-28 10:07:29 字數 4386 閱讀 2543

time limit: 1 second

memory limit: 128 mb

區間運算是數學的乙個領域。在區間運算中,常量和變數並不表示為乙個單獨、精確的值,而是表示為乙個有著上界和下界的區間

或範圍。在普通的運算中,乙個數量可以表示為數軸上的乙個點;而在區間運算中,乙個數量表示數軸上的一段,例如[3,5]表

示數軸上從3到5的一段。當精確的數值表示為區間時,上界與下界是相同的,如5表示為區間即[5,5]。

兩個區間的運算,是指乙個區間中的每個點與另乙個區間中的每個點所做的運算,通過運算所得的所有點的集合即為運算的結

果。例如,[3,5]+[-10,1]=[-7,6]。你的任務是寫乙個可以根據單行表示式進行取反數、加、減、乘、除等基本的區間運算的

程式。下面是一些運算的例子:

取相反數 -[-3,5]=[-5,3]

加法 [3,5]+[-10,1]=[-7,6]

減法 [3,5]-[-10,1]=[2,15]

乘法 [3,5]*[-10,1]=[-50,5]

除法 [3,5]/[-10,-0.1]=[-50,-0.3]

程式的輸入包含一行或多行區間運算的中綴表示式,每個區間都表示為[min,max],表 達式中包括括號、負號(-)、加號(+)、減號

(-)、乘號(*)和除號(/),括號可能是巢狀的。每一行中都有可能有空格,但空格不會在表示區間的括號「[min,max]」中間或

負號後出現。程式不需要處理科學記數法(如2e6=2000000)。每一行均不超過 80 個字元。運算採用標準的優先順序規則。下面按

優先順序遞減的順序給出各個運算子:

() 括號

- 取相反數

* / 乘法和除法,同級運算按從左往右的順序

+ - 加法和減法,同級運算按從左往右的順序

對於輸入的每一行,都相應地輸出一行,輸出的內容就是區間運算的最後結果,用[min,max]的形式表示,其中min不能大於max,

輸出結果都精確到小數點後第三位,區間形式中間不能有空格。但如果表示式裡面有除法,而且作為除數的區間包含0,則輸出

「division by zero」即可。

-[-3,5]

[3,5]+[-10,1]

[3,5]-[-10,1]

[3,5]*[-10,1]

(([3,5]/[-10,-0.1])/-[2,2])

[-5.000,3.000]

[-7.000,6.000]

[2.000,15.000]

[-50.000,5.000]

[0.150,25.000]

【題解】

對於進行的運算。

設a=[x1,y1],b=[x2,y2]

a+b = [x1+x2,y1+y2]

a-b = [x1-y2,y1-x2];

d1 = x1 m x2,d2 = x1 m y2,d3 = y1 m x2,d4 = y1 m y2;

a*b = [min(d1..d4,m=*),max(d1..d4,m=*)];

a/b = [min(d1..d4,m=/),max(d1..d4,m=/)];

對於取反。一開始的時候先判斷出哪些是取反符號(很容易就能想到要怎麼判斷的。)

然後在取反符號前加"([0,0]",然後在取反符號後面恰當的位置加上")"。就是把取反運算變成乙個減法

運算。然後利用二分的方法來求表示式。

具體的。

先找到乙個表示式裡面運算的優先級別最小的運算子。

然後遞迴這個運算子左邊的表示式。遞迴右邊的表示式。

如果當前處理的表示式全為區間。則返回這個區間的端點。存在struct結構體中。

這個遞迴也是乙個struct 結構體。所以可以直接返回。

同一優先順序別的操作符。往後找。這樣可以保證同一優先順序。從左到右運算的順序。

【**】

#include #include #include #include using namespace std;

struct qujian //結構體。存區間的端點

;bool chu0 = false; //用於判斷是否除0,因為不能直接結束程式。所以有點麻煩。

void check(string & s) //把多餘的空格去掉

bool reducebracket(string &s) //去掉兩邊的括號,如( (..) + (..))

s = s.erase(l,1); //去掉兩邊的括號

s = s.erase(1,1);

return true; //返回可以再嘗試去括號

}char cmp(char x,char y) //比較x操作符和y操作符的優先順序

int find (string s) //找s裡面運算子級別最小的運算子位置

while (b!=0);

}else

if ((s[i] == '*' || s[i] == '/' || s[i] == '+')

||(s[i] == '-' && i > 1 &&

(s[i-1] ==']' || s[i-1] == ')')

)) //這一大串都是判斷這個是不是操作符

i++; //無論如何都要遞增i

} else

i++;

} return k;

}double best_max(double x,double y,double z,double w) //返回幾個數中最大的數

double best_min(double x,double y,double z,double w) //返回幾個數中最小的數

qujian reduce(string s) //這是遞迴的主程式

bool judge = false; //判斷這個字串有沒有操作符

int l = s.size()-1;

for (int i = 1;i <= l;i++) //如果有操作符就返回true

if (s[i] == '*' || s[i] == '/' || s[i] == '+')

else //減號的判斷要小心出現負數的情況。這會麻煩點。

if (s[i] == '-' && i > 1 && (s[i-1] ==']' ||

s[i-1] == ')'))

if (!judge) //如果沒有出現操作符。則這是乙個區間

return temp;

} bool flag = reducebracket(s); //如果能去除兩邊多餘括號就去除

while (flag)

flag = reducebracket(s);

int k = find(s); //找到運算子的位置。

string sl = s.substr(0,k); //擷取運算子的左邊和右邊

char key = s[k]; //取出操作符

s = s.erase(1,k);//刪掉左邊,保留空格。所以從1開始

string sr = s; //右邊就直接等於刪掉後剩餘的東西

qujian temp1 = reduce(sl),temp2= reduce(sr);//遞迴左邊和右邊

if (chu0) //如果除0了就隨便返回個值。(沒用的)

return temp1;

qujian te***;

switch (key) //根據我在題解寫的規則進行運算,注意判斷除0

break;

case '/':

temp.r = best_max(temp1.l/temp2.l,temp1.l/temp2.r,

temp1.r/temp2.l,temp1.r/temp2.r);

temp.l = best_min(temp1.l/temp2.l,temp1.l/temp2.r,

temp1.r/temp2.l,temp1.r/temp2.r);

}break;

} return temp;

}void input_data()

while (b!=0);

s = s.insert(i,")");//加乙個右括號

i = j;//返回之前的位置。因為括號裡可能也有取反符

}if (s[i] == '[') //如果是個區間。只要到區間右邊加括號就好

ll = s.size();//要重新獲取字元長度

}i++; //遞增指標

}qujian l = reduce(s); //獲取答案區間

if (chu0) //是否除0做出判斷

printf("division by zero\n");

else

printf("[%.3lf,%.3lf]\n",l.l,l.r);

}}int main()

Swift 區間運算子

區間運算子 swift 提供了兩個方便表達乙個區間的值的運算子.閉區間運算子 閉區間運算子 a.b 定義乙個包含從 a 到 b 包括 a 和 b 的所有值的區間.閉區間運算子在迭代乙個區間的所有值時是非常有用的,如在 for in 迴圈中 1.for index in 1.5 4.1 5 5 5.2...

最小生成樹 找最小值 區間 運算修改

you are given an array ofnintegers.you should support the following queries on this array.first line of the input contains two space separated integer...

洛谷 T150188 區間(貪心,dp)

首先可以dp做,把資料離散化後dp i 表示到i位置的最多區間數。把所有區間按照右端點排序從左往右排序,求dp i 就用右端點為i的區間更新答案。狀態轉移可以看 這種做法常數較大,我們還可以用貪心解此題。我們依舊按照右端點排序,從左往右列舉所有區間,如果當前區間與前面沒有重疊 即此區間的左端點在前面...