昨晚原本準備在宿舍打cf的,結果吵吵鬧鬧的,也沒打成,頭也暈暈的,當時看了只看了第一個題,越想越麻煩,最後竟然陷入了誤區,半小時也沒解,雖然註冊了,一發也沒交。。。
Dima and Seryozha live in an ordinary dormitory room for two. One day Dima had a date with his girl and he asked Seryozha to leave the room. As a compensation, Seryozha made Dima do his homework.
The teacher gave Seryozha the coordinates of n distinct points on the abscissa axis and asked to consecutively connect them by semi-circus
in a certain order: first connect the first point with the second one, then connect the second point with the third one, then the third one with the fourth one and so on to the n-th
point. Two points with coordinates (x1, 0) and (x2, 0) should
be connected by a semi-circle that passes above the abscissa axis with the diameter that coincides with the segment between points. Seryozha needs to find out if the line on the picture intersects itself. For clarifications, see the picture Seryozha showed
to Dima (the left picture has self-intersections, the right picture doesn't have any).
Seryozha is not a small boy, so the coordinates of the points can be rather large. Help Dima cope with the problem.
Output
In the single line print "yes" (without the quotes), if the line has self-intersections. Otherwise, print "no"
(without the quotes).
Note
The first test from the statement is on the picture to the left, the second test is on the picture to the right.
題目意思很好懂,就看你怎麼去建立模型,簡化計算。早上起床靈光一閃。如果要是兩線相交的話,必然存在公共區域。可以直接列舉任意的兩條線,時間複雜度為O(10^6)。具體實現見程式碼。
AC程式碼:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[1005];
int main()
{
int n,i,j;
while(cin>>n)
{
for(i=0;i<n;i++)
cin>>a[i];
int flag =0,mi1,mi2,ma1,ma2;
for(i=0;i<n-1;i++)
{
mi1=min(a[i],a[i+1]);
ma1=max(a[i],a[i+1]); //第一條線mi1-ma1 第二條線mi2-ma2
for(j=i+2;j<n-1;j++)
{
mi2=min(a[j],a[j+1]);
ma2=max(a[j],a[j+1]);
if((mi2>mi1&&mi2<ma1&&ma2>ma1)||(mi2<mi1&&ma2>mi1&&ma2<ma1)) //相交
{
flag=1;
break;
}
}
if(flag) break;
}
if(flag) puts("yes");
else puts("no");
}
return 0;
}
/*
7
4 6 7 1 2 3 5
*/
這個題目如果看懂的話,相當easy,關鍵是要看懂。。當時第一題沒搞出來就直接沒看了。前面給你n個串,在每個串前面加上<3後面加上>3連結在一起。最後在連結好的串裡插入任意欄位。再給你一個串,問滿足條件否?
開始原先想的就是先比較<3然後跟串一個一個挨著比較,每比較完一個,就再匹配一個<3。具體實現見程式碼。最後還需要匹配一個<3.
程式碼:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
string a[100005];
string p;
int main()
{
int n,i,j;
while(cin>>n)
{
for(i=0;i<n;i++)
cin>>a[i];
cin>>p;
int flag=0;
int fla=0;
int s=0,t=0;
for(i=0;i<p.length();i++)
{
if(s==n)
{
fla=1;
break;
}
if(flag==0) //先匹配<
{
if(p[i]=='<')
flag=1;
}
else if(flag==1) //匹配3
{
if(p[i]=='3')
flag=2;
}
else
{
if(p[i]==a[s][t]&&t==a[s].length()-1)
{
s++;
t=0;
flag=0; //匹配一個串後需要重新匹配<3
}
else if(p[i]==a[s][t])
{
t++;
}
}
}
//cout<<s<<" "<<i<<endl;
flag=0;
if(fla) //匹配最後的<3
{
for(j=i;j<p.length();)
{
if(flag==0) //匹配<
{
if(p[j]=='<')
flag=1;
j++;
}
else if(flag==1) //匹配3
{
if(p[j]=='3')
{
fla=2;
break;
}
j++;
}
}
}
if(fla==2) puts("yes");
else puts("no");
}
return 0;
}
/*
3
i
love
you
<3i<3lo<3ve<3y<<<<<<<ou3<3
1
a
<3a<2
2
a
i
<3ai<3
*/
//46MS
後來仔細想可以先把滿足條件最簡單的串構造出來,再匹配。估計是用了string +,時間有點多。
程式碼:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
string a;
string p;
string tmp;
int main()
{
int n,i,j;
while(cin>>n)
{
a="<3"; //先加在最前面
for(i=0;i<n;i++)
{
cin>>tmp;
a=a+tmp;
a+="<3"; //每一串後面都加一個<3
}
//現在a串是最短長度的解
cin>>p;
int t=0,len=a.length();
for(i=0;i<p.length();i++)
{
if(t==len) break;
if(p[i]==a[t])
t++;
}
if(t==len) puts("yes");
else puts("no");
}
return 0;
}
//1684 ms
然後演算法設計老師講的一個題目蠻有意思的,給你兩根長短不同,粗細不均勻的繩子,我們僅僅知道每根繩子燒完需要1h,問怎麼才能使得兩根繩子都燒完,且剛好用時45min.
think........
用火機先點燃一根繩子的兩頭和另一根繩子的一頭。這樣用時30min,之後將剩下的繩子的另一頭點燃。
還有一個題目是關於公倍數的,求解%3=a,%5=b,%7=c,這樣的最小的正整數t,我們假設t=(5*7*s1)*a+(3*7*s2)*b+(3*5*s3)*c.我們只需要保證5*7*s1%3=1即可,因此s1取2,依次s2=1,s3=1。我們可以將他的一個解找到,然後+lcm(3,5,7)*k就是他的通解了,就可以求解了。