2020 6 7 普轉提

千年可貴一見,我竟然沒翻車???
awa
c++

成功進入了rank3,然鵝。。。

ui

 

 

 前8名全是前3。。。
妙趣橫生awa
只要拿到了基礎分的200,就是前3awa
哦對了,T4是本來的T1。。
T1是本來的T2,T2是本來的T3,T3是本來的T4
老師昨天題目加錯了。。。
因此就一大羣人A了T4 awa
快樂






spa

 

 

T1code

睿爸喜歡搭塔塔。blog

睿爸有h2個高度爲n1的紅色磚塊,和n2個高度爲h2的藍色磚塊,這些的磚塊的底面和頂面的長寬均相同,且你不能將這些磚塊立體旋轉或者轉動。字符串

睿爸能夠按照以下方式搭塔:get

1.每一個磚塊要麼能夠放在地面上,要麼必須壘在一個顏色不一樣的磚塊上面(一個磚塊上面僅能夠放一個磚塊)。string

2.至少須要一個磚塊,沒必要用完全部的磚塊。it

睿爸想知道這樣最多能夠搭出多少個不一樣高度的塔。io

給出n1,n2,h1,h2
簡單題,可是要long,long

直接給結論,隨便推一推就行了

 

#include <bits/stdc++.h>
#define ll long long
using namespace std ; ll a,b,x,y,ans; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int main() { freopen("tower.in","r",stdin); freopen("tower.out","w",stdout); a=read();x=read(); b=read();y=read(); if(a>b) { swap(a,b); } if(x==y) { ans+=a*2; } else { ans+=a*3; } if(a!=b)ans++; cout<<ans<<endl; return 0; }

 

T2

 

 題目的意思很是的補坑描述,我看了5分鐘纔看懂。。。
就是要你在一個字符串裏面在找出一個子序列(不用連續,可是要求順序不能倒)
取出之後,本來的序列要求變成取出的序列的一個排列,就是有且僅有取出的序列的所有字符
本來吧,若是真的是隻有我說的這些要求,那就是一道簡單題.
若是把題目裏面的字典序最小去掉,我分分鐘就能A了它,惋惜去不得
顯然,子序列T的合法要求就是,在原序列S中,每一個字符出現的次數必須是T中出現的次數的兩倍,不然必定不合法。
因此要若是不要保證字典序最小,這題就講完了。。。

awa







其實後面也不難搞,只用按位貪心一下,每一位都要貪心的選出可以保證後面合法的,且字典序最小的方案。
由於字典序自己就是一種貪心。。。
若是是判斷一個字母是否合法,只須要判斷前面字母使用的次數和用完之後還有幾個剩餘,就是正解了

awa

#include <bits/stdc++.h>
#define ll long long
using namespace std ; inline ll read() { register int Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int s[27],ss[27],ans[27][210],m=0,n; char ch[210]; void cherk() { for(int i=0;i<26;ss[i]=s[i],i++) { if(s[i]%2!=0) { puts("Clbtxdy!"); exit(0); } } } void work() { for(int i=1;i<=n;i++) { int mx=0; for(int j=i;j<=n;j++) { int x=ch[j]-'a'; bool ff=0; for(int k=0;k<26;k++) { if(x==k) { if(ans[k][j]>s[k]/2+1) { ff=1; break; } } else { if(ans[k][j]>s[k]/2) { ff=1; break; } } } if(!ff && ss[ch[j]-'a']>0) { if(mx==0) { mx=j; } else { if(ch[j]-'a'<ch[mx]-'a') { mx=j; } } } } if(mx==0) mx=i; cout<<ch[mx]; ss[ch[mx]-'a']-=2; s[ch[mx]-'a']+=2; m++; if(m==n/2) { exit(0); } i=mx; } } int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%s",ch+1); n=strlen(ch+1); for(int i=1;i<=n;i++) { s[ch[i]-'a']++; for(int j=0;j<26;j++) { if(ch[i]-'a'!=j) { ans[j][i]=ans[j][i-1]; } else { ans[j][i]=ans[j][i-1]+1; } } } cherk(); work(); return 0; }

T3

是個博弈論

 

 這個問題,有一個很麻煩的地方,就是若是是個dp的話,它的狀態會十分的複雜,由於我要同時去考慮兩種狀態:1.睿爸的。2.杜教的。
可是考慮到咱們最後的答案,其實要求的就是杜教扣了睿爸多少,因此就能夠把睿爸取到的數先所有都加上(包括杜教的),而後再減去所有的數(只有杜教的),這就是答案。

 

其中的A是睿爸能取到的數。
U是全集
因此咱們要作的事情其實就是最大化a[i]+b[i]。
那就很好搞啦!


可是這個並無到達博弈論的部分。
這只是爲了方便去計算咱們的答案罷了

 

如今問題已經被簡化了,咱們來討論一下博弈的策略。
由於答案和棧中的元素有關,而棧也是隻有兩個元素,因此這不就是在叫着:「討論我!討論我!」嗎。。。
對於一個棧的價值,其實就是如咱們上面說的,a[i]+b[i]。這個就是爲何先推出來上面的式子。
這個讓咱們討論價值這件事情變得可能。


結論1:若是一個棧的價值a+b<=c+d,先手永遠只能拿到上面的,然後手總能拿到下面的。
證實1:若是先手拿了一個棧頂,那麼後手必定是能夠直接拿棧底的
那若是他沒拿呢?

那先手就是憨。
由於沒拿,就說明了另外一個棧頂的元素確定是要比這個棧底大的。根據咱們的前提條件,先手拿的棧頂的元素是比棧頂小的。
拿爲何先手不拿這個棧頂呢?它不香嗎?

證畢。
awa

因而咱們就快樂的排除掉了a+b<=c+d的棧。由於他們的貢獻是十分顯然的。

接下來考慮一下a+b>c+d的棧。

結論2:對於a+b>c+d的棧,確定是前後手交替拿取目前最大的元素

證實2:
由於前面證實了最優的策略就是使拿到的元素兩個值相加起來最大。
因此咱們確定是要先拿取最大是元素的。
由於所有的棧都已是a+b>c+d了,因此不會存在衝突的狀況。
這樣就行了啊awa



ac!awa

#include <bits/stdc++.h>
#define ll long long
using namespace std ; ll a[200001],b[200001],c[200001],d[200001],n;bool vis[200001]; ll ans1,ans2; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int main() { freopen("dortmund.in","r",stdin); freopen("dortmund.out","w",stdout); n=read(); for(ll i=1;i<=n;i++) { a[i]=read();b[i]=read(); c[i]=read();d[i]=read(); } for(ll i=1;i<=n;i++) { if(a[i]+b[i]<=c[i]+d[i]) { ans1+=a[i]+b[i]; } } priority_queue<pair<ll,ll> > q; for(ll i=1;i<=n;i++) { if(a[i]+b[i]>c[i]+d[i]) { q.push(make_pair((a[i]+b[i]),i)); } } ll awsd=1; while(q.size()!=0) { // cout<<1<<endl; 
        pair<ll,ll> x=q.top(); ll now=x.first; if(awsd==1) { ans1+=now; awsd=2; } else { awsd=1; } if(vis[x.second]==false) { q.push(make_pair((c[x.second]+d[x.second]),x.second)); vis[x.second]=true; } q.pop(); } for(ll i=1;i<=n;i++) { ans1-=b[i]; ans1-=d[i]; } cout<<ans1<<endl; return 0; }

 

 

呼~總算是寫完了awa

 

T4

 

 

 

 

 

 一看就是圖論題(逃
一看就是最短路awa
這個嘛。。。
不就是最短路和dp的結合題嗎。。。
很典型啊。。。
最短路嘛,是有狀態的,因此像這總多了一個限制條件的問題,我想應該是可以用加一維狀態的辦法來解決的。
啥不行就給啥加狀態awa(逃
其實老是加狀態也是不行的,由於時空間複雜度撐不住啊awa
仍是要看狀況的awa







這個題解我是真的看不懂。。。

 

 直接放上來吧。。。
說的我好迷啊awa
淦,原來是我沒寫過幾道分層圖的dp。。。

我說爲何我最短路配dp老是不會寫。。。

不寫了,補坑去了awa

代碼用了機房dalao lsf的神奇dfs,跑的比正解還快,並且好寫。。。
本質就是一個樸素的dfs。。。。
code

#include <bits/stdc++.h>
#define ll long long
using namespace std; struct edge { ll to,next,v;bool f; }e[10001]; ll head[10001],tot,n,m,k;bool vis[10001],vis2[10001];int dis[1001][20],ans=INT_MAX; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } void add(int i,int j,int v,bool flag) { e[++tot].next=head[i]; e[tot].to=j; head[i]=tot; e[tot].v=v; e[tot].f=flag; } void dfs(int x,int sum,int cnt) { if(cnt>k) { return ; } if(vis[x]==true) { ans=min(ans,sum); return ; } if(sum>=dis[x][cnt]) { return ; } vis[x]=true; dis[x][cnt]=sum; for(int i=head[x];i!=0;i=e[i].next) { int u=e[i].to; dfs(u,sum+e[i].v,cnt+(e[i].f?1:0)); } vis[x]=false; } int main() { freopen("trolley.in","r",stdin); freopen("trolley.out","w",stdout); n=read();m=read();k=read(); for(int i=1;i<=n;i++) { int x=read(),y=read(),v=read(); add(x,y,v,false); } for(int i=1;i<=abs(m-n);i++) { int x=read(),y=read(),v=read(); add(x,y,v,true); } memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=k;i++) { dis[0][i]=0; } dfs(1,0,0); cout<<ans<<endl; return 0; }

the end 撒花awa

相關文章
相關標籤/搜索