http://codeforces.com/contest/909
差F題了,有機會再補吧。F是思維題。
斷斷續續補了好久。。
比賽就做了A,B 。
A
給你兩個名字,要求一個名字由這兩個的前綴拼接順序而成並且字典序最小。
把問題轉化一下,想要長度最小,最後一個名字只取首字母。
然後在第一個名字內找比 二名字首字母小的字母
#include <bits/stdc++.h>
using namespace std;
int main()
{ string a,b;
cin>>a>>b;
string w;
w+=a[0];
for(int i=1;i<a.length();i++){
if(a[i]<b[0])
w+=a[i];
else break;
}
w+=b[0];
cout<<w<<endl;
return 0;
}
B給定一個長度n,求1-n之間長度小於等於n的所有線段,可以累加成多少線段。
數據範圍100,一看圖就知道啥意思,暴力
#include <bits/stdc++.h>
using namespace std;
int sum[200];
int main()
{ int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
for(int j=i;j<=m;j++){
for(int k=i;k<=j;k++)
sum[k]++;
}
}
int max1=-1;
for(int i=1;i<=m;i++)
max1=max(sum[i],max1);
cout<<max1<<endl;
return 0;
}
c python大法好。
給定兩個字母。s爲正常語句,f爲循環語句。問有多少縮進形式。
最開始的思路是 統計f字串長度,然後快速冪qwq
有點迷,我現在都忘記爲啥這樣寫了 。。
正解:dp,當f時,狀態轉移方程爲
dp[i][j]=dp[i-1][j-1];//有i行,第i行 縮進爲j時的狀態。
有f就縮進加1。嚴格縮進。
當爲s時。
大縮進 可以往小縮進移動(縮進越大,距離左端越大。)
求一遍後綴和。
#include <bits/stdc++.h>
using namespace std;
/* 動態規劃問題。
考慮一點,那就是我們最後的結束,肯定是語句爲界
對於有F語句的,是之前上一行的各個 縮進矩陣取一下就行
對於S語句,我們就求和就行。
*/
const int maxn=5006;
int dp[maxn][maxn];
typedef long long ll;
const ll mod=1e9+7;
int m;
char ch;
int main()
{ scanf("%d",&m);
getchar();
dp[0][0]=1;
for(int i=1;i<=m;i++){
//scanf(" %c",&ch);
ch=getchar();
if(ch=='f'){
for(int j=0;j<=i-1;j++){
dp[i][j+1]=dp[i-1][j];
}
}
else{
ll sum=0;
for(int j=m;j>=0;j--){
sum=(sum+dp[i-1][j])%mod;
dp[i][j]=sum;
}
}
getchar();
}
//cin>>ch;
/*for(int i=0;i<=m;i++){
for(int j=0;j<=m;j++){
printf("%d ",dp[i][j]);
}
cout<<endl;
}
/*for(int i=m;i>=0;i--){
if(dp[m][i]!=0){
printf("%lld\n",dp[m][i]);
break;
}
}*/
printf("%d\n",dp[m][0]);
return 0;
}
D:給定一個字符串,如果第i的位置和 他相鄰的不想等,就把他們刪掉,有一個不想等刪倆,兩個相鄰的都不想等就刪除3。
思路:如果暴力實在是有點。。 放D題幹嘛。
並且我發現 list並沒有刪除 節點的O(1)的函數。暗道自己寫一個循環鏈表? 最後沒有寫,感覺不應該是這樣。
維護一個vector。表示每段。然後暴力。
#include <bits/stdc++.h>
using namespace std;
/* 加油啊。 爲未來
暴力的寫法,
我自己不I昂I想你
*/
vector<pair<char,int> >v;
vector<pair<char,int> >s;
string ss;
int main(){
cin>>ss;
long long ans=0;
v.push_back(make_pair(ss[0],1));
for(int i=1;i<ss.length();i++){
//if(v.size()==0)
//v.push_back(make_pair(ss[i],1));
if(ss[i]==v[v.size()-1].first)
{ v[v.size()-1].second++;
}
else
v.push_back(make_pair(ss[i],1));
}
/*for(int i=0;i<v.size();i++){
cout<<v[i].first<<" "<<v[i].second<<"::";
}*/
//cout<<endl;
s.clear();
while(v.size()>1){
s.clear();
for(int i=0;i<v.size();i++){
if(i==0||i==(v.size()-1))
v[i].second-=1;
else
v[i].second-=2;
}
ans++;
int aa=0;
while(v[aa].second<=0&&aa<v.size()) aa++;
//這個循環沒有aa<v.size()是會re的。比方說ababababa這 種情況。,第一次這個循環就不會停。。
s.push_back(v[aa]);
for(int i=aa+1;i<v.size();i++){
if(v[i].second<=0){
continue;
}
else{
//if(s.size()==0) s.push_back(v[i]);
if(v[i].first==s[s.size()-1].first){
s[s.size()-1].second+=v[i].second;
}
else
s.push_back(v[i]);
}
}
/*for(int i=0;i<s.size();i++){
cout<<s[i].first<<" "<<s[i].second<<"::";
}
cout<<endl;
*/
v=s;
}
printf("%lld\n",ans);
return 0;
}
E:給定一個有向 圖(前趨圖?),表示每個任務的依賴關係,a連b表示b依賴a, 當a完成了,b才能完成。
有的處任務只能在主處理器上做有的只能在協處理器,當一個任務所依賴的任務都完成或者都在 一個處理器上,我們就把他們放在一個處理器上,
問最少需要多少協處理器。
一種是類似暴力的方法,記錄每個任務所依賴的事件個數,然後存一個 主處理器隊列和 協處理器隊列,循環bfs。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,mm;
cin>>n>>mm;
vector<int>typ(n);
vector<vector<int> >g(n);
for(int i=0;i<n;++i) cin>>typ[i];
vector<int>cnt(n,0);
for(int i=0;i<mm;++i)
{
int x1,x2;
cin>>x1>>x2;
g[x1].push_back(x2);
cnt[x2]++;
}
queue<int> c,m;
for(int i=0;i<n;++i)
{
if(cnt[i]==0)
{
if(typ[i]==0) m.push(i);
else c.push(i);
}
}
//cout<<c.size()<<' '<<m.size()<<'\n';
int ans=0;
while(!c.empty()||!m.empty())
{
while(!m.empty())
{
int x=m.front();
for(int i=0;i<g[x].size();++i)
{
cnt[g[x][i]]--;
if(cnt[g[x][i]]==0)
{
if(typ[g[x][i]]==0) m.push(g[x][i]);
else c.push(g[x][i]);
}
}
m.pop();
}
if(!c.empty()) ++ans;
while(!c.empty())
{
int x=c.front();
for(int i=0;i<g[x].size();++i)
{
cnt[g[x][i]]--;
if(cnt[g[x][i]]==0)
{
if(typ[g[x][i]]==0) m.push(g[x][i]);
else c.push(g[x][i]);
}
}
c.pop();
}
}
cout<<ans;
return 0;
}
另一個版本
#include <bits/stdc++.h>
using namespace std;
/* 1可以發現他們的遞歸關係。
U爲根,v爲所依賴的(U->v有一條邊。)
那麼 T(U)=max(T(s)+S,T(u));
當u在協處理器上時而V全在主處理器上時。S爲1
否則S爲0.
2 用topsort的方法來寫。
其實還是那個遞歸關係啦。
PS:我之前寫過一個 topsort。但是我是把所有的葉子節點給鏈接到一起。
因爲 我感覺 就算沒有鄰接關係的點也是可能在一個主處理器上。
而我是使用 u,v是否相等來判斷 協處理器 的數量。。 這樣會多算。
但是 這樣寫了 破壞了原來的鄰接關係。樣例1就不對。
分析 6種情況:
1 U,V均爲協處理器,不增加。(可以放到一個協處理器上)
2 u爲協,v全爲主,加1
3 u爲協,V部分爲協,v部分一定在一個協處理器上。
4 u爲主,v爲協,不加。v在一起
4 u爲主,v爲主,不加。v在一起
6 u爲主,v主協均有。 v在一起
然後維護最大的T就行。
注意有多個根,用記憶化維護一下。
不記憶化會T。
*/
const int maxn=1e5+200;
int t[maxn];
vector<int>g[maxn];
int typ[maxn];
int du[maxn];
bool vis[maxn];
void dfs(int u,int pre){
int sum=0;
//cout<<u<<" "<<g[u].size()<<" "<<t[u]<<endl;
if(!g[u].size()&&typ[u]==1&&!vis[u])
{t[u]++;
//cout<<u<<"zuobiao"<<endl;
vis[u]=true;
return;}
vis[u]=true;
for(int i=0;i<g[u].size();i++){
if(g[u][i]==pre) continue;
int to=g[u][i];
if(!vis[to])
dfs(to,u);
if(typ[to]==0&&typ[u]==1)
t[u]=max(t[u],t[to]+1);
else
t[u]=max(t[u],t[to]);
}
//else if(sum<g[u].size()&&typ[u]==1)
//t[u]=1;
return;
}
int main()
{ int m,n,a,b;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%d",&typ[i]);
}
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
g[a].push_back(b);
du[b]++;
}
int aim=0;
for(int i=0;i<m;i++){
if(!du[i]){
aim=i;
dfs(i,-1);
//break;
}
}
int maxx=-1;
for(int i=0;i<m;i++){
maxx=max(maxx,t[i]);
//cout<<t[i]<<" ";
}
printf("%d\n",maxx);
return 0;
}