1개의 댓글이 있습니다.
-
-
Taeyoon_Lee -
저는 1000점 문제를 mincost-maxflow로 풀었어요. 알파벳에 해당하는 간선 빼고, 나머지 모든 간선에 cost를 0으로 합니다. 알파벳에 해당하는 간선은 사전순으로 적당히 큰 값으로 오름차순이 되게 cost를 정하면 됩니다. (저는 '10000+아스키코드값'으로 했어요.)
maxflow나 mincost-maxflow나 둘다 라이브러리로 만든 걸 이용해서 쓰는데, edmond-karp를 구현한 maxflow로는 사전순으로 먼저 유량을 흘리는 게 불가능할 것 같더라고요.
17년 전 link
-
-
정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.

ipknHama
겨울방학 SRM 모임 첫 연습이었습니다.
ipkn, domeng, libe, dgsquare, altertain, xhae 님이 참가했었고,
세 개 다풀어서 오오! 했다가 systest에 orz 했네요.
300 WindowManager여러 개의 네모 상자가 주어질 때, 문제에 주어진대로 해당 상자를 칠하는 문제입니다. 상자의 크기는 가로 세로 100000000까지로, 매우 큰 상자가 입력으로 들어올 수 있지만, 실제로 그려야 하는 영역은 100x100의 크기이기 때문에, 50 (각 상자 수) * 100 * 100 의 시간으로 해결할 수 있는 문제였습니다.
~~~ cpp
#includescreen(int height, int width, vector windows) v;
{
#include
#include
#include
using namespace std;
class WindowManager
{
public:
vector
{
vector
v.resize(height);
v[0] = "";
for(int i = 0; i < width; i ++)
v[0] += " ";
for(int i = 1; i
v[i] = v[0];
}
for(int i = 0; i < windows.size(); i ++)
{
istringstream is(windows[i]);
int tlv, tlh, vs, hs;
string fills;
is >> tlv >> tlh >> vs >> hs >>fills;
char fill = fills[0];
for(int j = max(tlv, 0); j < min(tlv+vs, height);j++)
for(int k = max(tlh, 0); k < min(tlh+hs, width); k++)
{
if (j == tlv || j == tlv + vs-1)
{
if (k == tlh || k == tlh + hs - 1)
{
v[j][k] = '+';
}
else
v[j][k] = '-';
}
else if (k == tlh || k == tlh + hs - 1)
{
v[j][k] = '|';
}
else
v[j][k] = fill;
}
}
return v;
}
};
1000 Graduation졸업하기 위해선 만족시켜야 하는 규칙들이 주어집니다. 규칙들은 다 동일한 형태로, 어떤 과목들 중에서 k개 이상의 과목을 들어야 한다 라는 조건입니다. 즉, 2ABCD 라면, A, B, C, D 중에서 두 과목 이상을 들어야 이 규칙을 만족시킬 수 있습니다. 또 동시에 한 과목은 두 규칙을 만족시키는데 사용될 수 없습니다. 즉, 2ABC, 2BCD라는 두 규칙이 있다면, AB는 2ABC를, CD는 2BCD를 만족시키는데 사용되는 방법밖에 없습니다.
현재 수강한 과목들이 주어질 때, 어떤 과목들을 추가로 더 수강하면 규칙들을 모두 만족시킬 수 있는지 구하는 문제입니다. 단, 수강해야하는 과목 수는 최소로 해야하고, 최소인 여러가지 경우 중에서 수강하는 과목의 알파벳들이 사전순으로 제일 앞서는 경우를 구해야합니다.
이 문제는 네트워크 플로우를 이용하여 해결할 수 있습니다. source와 sink를 하나 두고, source에 각 과목들로 가는 가중치 1의 간선과,
과목에서 자신과 관련있는 규칙들로 가는 가중치 1의 간선, 그리고 규칙 별로 수강해야하는 과목 수와 같은 가중치를 가지는 sink로 가는 간선을 추가하여, maximum flow를 구했을 때, 그 값이 규칙별 수강해야하는 과목 수 합과 같으면 해당 규칙들을 만족할 수 있습니다.
여기서 기존에 들은 과목을 포함하여 사전적으로 제일 먼저인 수강할 과목 목록을 구해야 하는데, 저는 maximum flow를 계산할 때 수강한 과목 이거나 알파벳으로 우선하는 과목을 먼저 방문하도록 path를 찾도록 해서 해결했습니다. 그 외에 다른 방법들도 있을 수 있습니다.
~~~ cpp
#include
m[i][j] = f[i][j] = 0; rs) rc;
{
{
#include
#include
#include
using namespace std;
int on;
int n;
int m[200][200];
int f[200][200];
class Graduation
{
public:
string order;
int idx(char c)
{
for(int i = 0; i < order.size(); i ++)
if (c == order[i])
return i;
return -1;
}
int v[200];
int p[200];
int fl;
int dfs(int s,int e, int l = 0)
{
p[l] = s;
v[s] = 1;
if (s == e)
{
fl = l;
return 1;
}
for(int i = 0 ; i < n; i ++)
if ((m[s][i]-f[s][i])>0 && !v[i])
{
int ret = dfs(i, e,l+1);
if (ret)
return 1;
}
// v[s]=0;
return 0;
}
int maxflow(int s, int e)
{
int cost = 0;
while(1)
{
for(int i = 0; i < n; i ++) v[i] = 0;
if (dfs(s, e))
{
int v = 20000;
for(int i = 0; i < fl; i ++)
{
if (v > m[p[i]][p[i+1]]-f[p[i]][p[i+1]])
v = m[p[i]][p[i+1]]-f[p[i]][p[i+1]];
}
cout << v ;
cout << endl;
cost += v;
for(int i = 0; i < fl; i ++)
{
f[p[i]][p[i+1]] += v;
f[p[i+1]][p[i]] -= v;
}
}
else
break;
}
return cost;
}
void clear(int n )
{
for(int i = 0; i < n; i ++)
for(int j = 0;j
}
void addedge(int a, int b, int c)
{
m[a][b] = c;
}
string moreClasses(string ct, vector
{
sort(ct.begin(),ct.end());
order = ct;
for(char c = 33; c <= 126; c ++)
{
if (c >= '0' && c <= '9')
continue;
if (find(ct.begin(), ct.end(), c)==ct.end())
order += c;
}
int totalcost = 0 ;
vector
for(int i = 0; i
int v = 0;
for(int j = 0; j < rs[i].size(); j ++)
{
if (rs[i][j] >= '0' && rs[i][j] <= '9')
{
v*=10;
v+=rs[i][j] - '0';
}
else
break;
}
rc.push_back(v);
totalcost += v;
}
n = order.size();
on = n;
n += rs.size();
int vs = n ++; // s;
int ve = n ++; // e;
clear(n);
for(int i = 0; i < rs.size(); i ++)
{
int c = rc[i];
for(int j = 1;j
if (rs[i][j] < '0' || rs[i][j] > '9')
{
cout << rs[i][j];
addedge(idx(rs[i][j]), on+i, 1);
}
}
addedge(on+i, ve, c);
}
for(int i = 0; i < order.size(); i ++)
{
addedge(vs, i, 1);
}
int cost = maxflow(vs, ve);
if (cost < totalcost)
return "0";
string s;
for(int i = ct.size(); i < order.size(); i ++)
{
if (f[vs][i])
{
s += order[i];
}
}
return s;
}
};
17년 전