Codeforces Round #288 (Div. 2) A,B,C,D,E
A:一個一個點向圖裡面加,判斷其所在的位置與其他的點是否可以構成小矩形就可以了。
B:貪心,如果前面的偶數有比他小的就找到一個最靠前的交換,如果前面的偶數都比它小,就找一個最靠後的交換。
C:貪心,把蠟燭儘可能的放在惡魔,來之前,這樣可以充分利用蠟燭的時間,模擬一下,不停地向前方就可以了。如果蠟燭時間小於需要的數目,一定不可以。
<span style="font-size:18px;">const int maxn = 2010;
int vis[maxn];
int num[maxn];
int main()
{
int m, t, r;
while(cin >>m>>t>>r)
{
for(int i = 1; i <= m; i++)
scanf("%d",&num[i]);
if(r > t)
{
puts("-1");
continue;
}
int ans = 0;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= m; i++)
{
int x = num[i]-1;
while(vis[num[i]+1000] < r)
{
for(int k = x-1; k <= x+t; k++)
vis[k+1000]++;
ans++;
x --;
}
}
cout<<ans<<endl;
}
}</span>
D:尤拉路徑+列印路徑。
判斷尤拉路徑的方法是,統計出來他的度(入度+, 出度-)。如果所有的度均為0,或者只有一對度數為(+1,-1)的,那麼就可以構成路徑。但是這題還必須保證字串的數目,所以判斷之後,還有跑一遍dfs求出長度,判斷長度是否滿足條件。
列印路徑的時候,先dfs再儲存邊,這樣可以保證一開始存的邊一定是距離“起點”最遠的。
<span style="font-size:18px;">const int maxn = 200010;
char str[maxn][10];
int deg[maxn];
int ans[maxn];
int vis[maxn];
int cur[maxn];
vector<pair<int, int> > G[maxn*3];
int cnt;
int Get(char x)
{
if ('0' <= x && x <= '9')return x-'0';
if ('a' <= x && x <= 'z')return x-'a'+10;
return x-'A'+36;
}
int get_x(int x)
{
return Get(str[x][0])*62+Get(str[x][1]);
}
int get_y(int y)
{
return Get(str[y][1])*62+Get(str[y][2]);
}
void dfs(int x, int y)
{
int xp;
int n = G[x].size();
while(cur[x] < n)
{
if(!vis[G[x][xp = cur[x]++].second])
{
vis[G[x][xp].second] = 1;
dfs(G[x][xp].first, G[x][xp].second);
}
}
ans[cnt++] = y;
}
bool judge(int n)
{
int x = 0;
int y = 0;
int pos = get_x(0);
for(int i = 0; i < 62*62+100; i++)
{
if(deg[i] > 1 || deg[i] < -1) return false;
if(deg[i] == 1)
{
x++;
pos = i;
}
if(deg[i] == -1) y++;
}
if(x != y || x > 1) return false;
dfs(pos, -1);
cnt--;
return cnt >= n;
}
int main()
{
int n;
while(cin >>n)
{
memset(cur, 0, sizeof(cur));
memset(vis, 0, sizeof(vis));
memset(deg, 0, sizeof(deg));
cnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%s", str[i]);
int x = get_x(i);
int y = get_y(i);
G[x].push_back(make_pair(y, i));
deg[x]++;
deg[y]--;
}
if(!judge(n))
{
cout<<"NO"<<endl;
continue;
}
puts("YES");
printf("%s",str[ans[cnt-1]]);
for(int i = cnt-2; i >= 0; i--)
printf("%s", str[ans[i]]+2);
puts("");
}
return 0;
}
/*
6
abc
bca
cab
cad
adc
dca
*/</span>
E:有兩種解法。一種是貪心,一種是dp。
貪心的話,就是把這個當前的括號能匹配到的範圍放入棧頂,如果有的右短點位於這個區間之間就出棧。如果棧空了,還有沒匹配到的就說明是不合法的。就是讓近的儘可能的早點匹配出去。
貪心,解法:
const int maxn = 610;
struct node
{
int l, r;
}f[maxn];
char str[maxn*2];
int main()
{
int n;
while(cin >>n)
{
for(int i = 1; i <= n; i++)
scanf("%d %d",&f[i].l, &f[i].r);
stack<pair<int , int> > st;
int top = 0;
int flag = 0;
for(int i = 1; i <= n; i++)
{
st.push(make_pair(f[i].l+top, f[i].r+top));
str[top++] = '(';
while(!st.empty() && st.top().first <= top && top <= st.top().second)
{
str[top++] = ')';
st.pop();
}
if(!st.empty() && top > st.top().second)
{
flag = 1;
break;
}
}
if(flag || !st.empty())
{
puts("IMPOSSIBLE");
continue;
}
for(int i = 0; i < top; i++) cout<<str[i];
cout<<endl;
}
}
dp:dp的解法就是區間dp,dp[i][]表示第i個左括號到第j個左括號已經成功匹配。我們列舉第i到j之間的右括號的位置為k,那麼if(dp[i+1][k] && dp[k+1][j]) dp[i][j] = 1。1代表可以匹配額,0代表不可以匹配。
dp解法:
const int maxn = 610;
int dp[maxn][maxn];
char str[maxn*2];
int len[maxn*2];
struct node
{
int l, r;
} f[maxn];
bool dfs(int x, int y)
{
if(x > y) return true;
if(dp[x][y] != -1) return dp[x][y];
for(int i = x; i <= y; i++)
{
if(i-x+1 >= f[x].l && i-x+1 <= f[x].r)
{
if(dfs(x+1, i) && dfs(i+1, y))
{
dp[x][y] = 1;
len[x] = 2*(i-x)+1;
return true;
}
}
}
dp[x][y] = 0;
return false;
}
///dp[i][j]表示第i個到第j個左括號是否都成功的匹配到了右括號
///對於dp[i][j] ,我們列舉i被第幾個右括號匹配了.
///從i個右括號列舉到第j個右括號,假設被第k個右括號匹配並且滿足之前給的範圍了
///那麼我們需要判斷其子狀態 dp[i + 1][k],以及dp[k+1][j]是可以成功匹配
int main()
{
int n;
while(cin >>n)
{
int flag = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d %d",&f[i].l, &f[i].r);
if(!(f[i].l%2)) f[i].l++;
if(!(f[i].r%2)) f[i].r--;
if(f[i].l > f[i].r) flag = 1;
f[i].l = (f[i].l+1)/2;
f[i].r = (f[i].r+1)/2;
}
if(flag)
{
puts("IMPOSSIBLE");
continue;
}
memset(dp, -1, sizeof(dp));
memset(str, 0, sizeof(str));
if(!dfs(1, n))
{
puts("IMPOSSIBLE");
continue;
}
int ans = 0;
for(int i = 1; i <= n; i++)
{
while(str[ans] == '(' || str[ans] == ')') ++ans;
str[ans] = '(';
str[ans+len[i]] = ')';
}
puts(str);
}
return 0;
}
相關文章
- Codeforces Round #287 (Div. 2)A,B,C,D,E
- Codeforces Round #280 (Div. 2 A,B,C,D,E)
- Codeforces Round #290 (Div. 2) A,B,C,D
- Codeforces Round #401 (Div. 2)(C,D,E)
- Codeforces Round #283 (Div. 2) D,E
- Codeforces Round #251 (Div. 2) A/B/D
- Codeforces Round 965 (Div. 2) 補題記錄(A,B,D,E1)
- Codeforces Round 892 (Div. 2) E
- Codeforces Round 936 (Div. 2) E
- Codeforces Round 945 (Div. 2) (A - E)
- Codeforces Round 975 (Div. 2)題解記錄(A,B,E)
- Codeforces Round 977 (Div. 2)(B-C2)
- Codeforces Round #229 (Div. 2)(C,E待續)
- Codeforces Round #448 (Div. 2)B
- Codeforces Round #450 (Div. 2) B
- Codeforces Round #452 (Div. 2) D
- Codeforces Round 941 (Div. 2) D
- Codeforces Round 960 (Div. 2)(A - D)
- Codeforces Round #846 (Div. 2) A-E
- Codeforces Round #851 (Div. 2) A-E
- Codeforces Round #681 (Div. 2)E題解
- Codeforces Round #361 (Div. 2) E 費馬小
- Codeforces Round #676 (Div. 2) A - D個人題解(E題待補)
- Codeforces Round #325 (Div. 2) D bfs
- Codeforces Round #250 (Div. 2) A-D
- Codeforces Round #256 (Div. 2)A-D
- Codeforces Round 976 (Div. 2) and Divide By Zero 9.0(A,B,C)IDE
- codeforces Educational Codeforces Round 33 (Rated for Div. 2)B
- Codeforces Round #453 (Div. 2) C
- Codeforces Round #452 (Div. 2) C
- Codeforces Round 973 (Div. 2) C
- Codeforces Round 972 (Div. 2) C
- Codeforces Round 982 (Div. 2)(A~C)
- Codeforces Round #362 (Div. 2) B 模擬
- Codeforces Round #336 (Div. 2) B 暴力
- Codeforces Round #325 (Div. 2) B 遞推
- Codeforces Round #245 (Div. 2) B - Balls GameGAM
- Codeforces Round #316 (Div. 2) E dp