Andrew Stankevich's Contest #5
Solution
Problem A: UniqueAttack
Problem B: BurningBridges
Problem C: Circles
Problem D: LinearProgramming Dual
Problem E: DVD
Problem F: ThinkPositive
Problem G: Ranking
Problem H: DrivingStraight
August 2nd,2013 by chlxyd,xioumu
Problem A: UniqueAttack
给一个流,问最小割是否唯一。
Solution
Tag:网络流
先求一遍网络流。
1. 源点和汇点最后bfs到的点是一样的:显然最小割唯一,就是源点和汇点的公共bfs点。
2. 源点和汇点最后bfs到的点是不一样的(部分一样):那么s bfs到的那些点是原图的一个最小割,t bfs到的那些点是原图的一个最小割,最小割不唯一。
综上,扫描s和t bfs到的点是否是所有点就行。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clr(x) memset(x,0,sizeof(x))
#define clrs( x , y ) memset(x,y,sizeof(x))
#define out(x) printf(#x" %d\n", x)
#define sqr(x) ((x) * (x))
typedef long long lint;
const int maxint = -1u>>1;
const double eps = 1e-8;
const int maxn = 1000;
int flag;
int n , m , A , B ;
bool bj[maxn] ;
int sgn(const double &x) { return (x > eps) - (x < -eps); }
struct Graph1 {
struct Adj {
int v, c, b;
Adj(int _v, int _c, int _b) :
v(_v), c(_c), b(_b) {}
Adj(){}
};
int n, S, T, h[maxn], cnt[maxn];
vector<Adj> adj[maxn];
void clear() {
for (int i = 0; i < n; i++) {
adj[i].clear();
}
n = 0;
}
void insert(int u, int v, int c, int d = 0) {
n = max(n, max(u, v) + 1);
adj[u].push_back(Adj(v, c, adj[v].size()));
adj[v].push_back(Adj(u, c * d, adj[u].size() - 1));
}
int maxflow(int _S, int _T) {
S = _S, T = _T;
fill(h, h + n, 0);
fill(cnt, cnt + n, 0);
int flow = 0;
while (h[S] < n) {
flow += dfs(S, maxint);
}
return flow;
}
int dfs(int u, int flow) {
if (u == T) {
return flow;
}
int minh = n - 1, ct = 0;
for (vector<Adj>::iterator it = adj[u].begin(); flow && it != adj[u].end(); ++it) {
if (it->c) {
if (h[it->v] + 1 == h[u]) {
int k = dfs(it->v, min(it->c, flow));
if (k) {
it->c -= k;
adj[it->v][it->b].c += k;
flow -= k;
ct += k;
}
if (h[S] >= n) {
return ct;
}
}
minh = min(minh, h[it->v]);
}
}
if (ct) {
return ct;
}
if (--cnt[h[u]] == 0) {
h[S] = n;
}
h[u] = minh + 1;
++cnt[h[u]];
return 0;
}
void dfs1( int s ) {
if ( !bj[s] ) {
flag ++ ;
bj[s] = true ;
}
else return ;
for (vector<Adj>::iterator it = adj[s].begin(); it != adj[s].end(); ++it) {
if ( it->c > 0 )
dfs1(it->v) ;
}
}
void dfs2( int s ) {
if ( !bj[s] ) {
flag ++ ;
bj[s] = true ;
}
else return ;
for (vector<Adj>::iterator it = adj[s].begin(); it != adj[s].end(); ++it) {
if ( adj[it->v][it->b].c > 0 )
dfs2(it->v) ;
}
}
bool check( ){
return flag == n ;
}
}G;
int main(){
while ( scanf("%d %d %d %d" , &n , &m , &A , &B ) == 4 ) {
if ( A == 0 && B == 0 && n == 0 && m == 0) return 0 ;
G.clear() ;
repf( i , 0 , n - 1 ) bj[i] = 0 ;
repf( i , 1 , m ) {
int a , b , c ;
scanf("%d %d %d" , &a , &b , &c ) ;
G.insert( a - 1 , b - 1 , c , 1 ) ;
}
flag = 0 ;
A -- ; B -- ;
G.dfs1(A) ; G.dfs2(B) ;
int tmpn = n ;
rep( i , n ) if ( !bj[i] ) tmpn -- ;
if ( tmpn != n ) while (1 ) ;
flag = 0 ;
int flow = G.maxflow(A,B) ;
clr(bj) ;
G.dfs1(A) ;
G.dfs2(B) ;
printf("%s\n" , flag == n ? "UNIQUE" : "AMBIGUOUS" ) ;
}
}
Problem B: BurningBridges
给一个无向图,求桥。
Solution
Tag:图论,tarjan
Tarjan模板题,网上资料很多,不赘述。
/*
* Author: chlxyd
* Created Time: 2013/7/22 12:39:43
* File Name: B.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
map<int,int> mp[10010] , e[10010] ;
vector<int> v[10010] , ans ;
int dfn[10010] , low[10010];
int visit[10010] ;
int T , n , m , temp;
int a[100010] , b[100010] ;
void dfs( int i , int fa , int dep ) {
dfn[i] = low[i] = dep ;
visit[i] = 1 ;
rep( j , v[i].size() ) {
int k = v[i][j] ;
if ( visit[k] == 1 && k != fa )
low[i] = min( low[i] , dfn[k] ) ;
else if ( visit[k] == 0 ) {
dfs(k,i,dep+1) ;
low[i] = min( low[i] , low[k] ) ;
if ( low[k] > dfn[i] && mp[i][k] == 1 ) {
ans.push_back(e[i][k]) ;
}
}
}
visit[i] = 2 ;
}
int main(){
//int T;
scanf("%d", &T);
repf( t , 1 , T ) {
if ( t != 1 ) puts("") ;
scanf("%d %d" , &n , &m ) ;
repf( i , 1 , n ) {
visit[i] = 0;
dfn[i] = low[i] = 0 ;
mp[i].clear() ;
e[i].clear() ;
v[i].clear() ;
}
repf( i , 1 , m ) {
scanf("%d %d" , &a[i] , &b[i] ) ;
mp[a[i]][b[i]] ++ ;
mp[b[i]][a[i]] ++ ;
e[a[i]][b[i]] = i ;
e[b[i]][a[i]] = i ;
if ( mp[a[i]][b[i]] == 1 ) {
v[a[i]].push_back(b[i]);
v[b[i]].push_back(a[i]) ;
}
}
temp = 0 ;
ans.clear() ;
dfs(1,0,1) ;
printf("%d\n" , ans.size() );
if ( ans.size() != 0 ) {
sort( ans.begin() , ans.end() ) ;
}
rep( i , ans.size() ) {
if ( i != 0 ) printf(" ") ;
printf("%d" , ans[i] ) ;
}
if ( ans.size() != 0 )
puts("") ;
}
}
Problem C:
给你很多个圆,问这些圆把平面分成了多少块。
Solution
Tag:计算几何,欧拉公式
先将这些圆组成的图转化成一个平面图,然后就可以用欧拉公式来算平面分成了多少块了。
平面图的欧拉公式是1=V-E+F,即F=E-V+1,F是被分成了多少块,V是顶点,E是边数。这个公式只适用与连通图。所以这题要把所有连通分量单独算,最后相加。
计算出所有圆的交点,一个圆上有多少个交点说明这个圆为这个圆所在的连通分量提供了多少条边和点。
然后通过边数和点数用欧拉公式算出答案。
/*
* Author: xioumu
* Created Time: 2013/7/27 17:35:37
* File Name: C.cpp
* solve: C.cpp
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clr(x) memset(x,0,sizeof(x))
#define clrs( x , y ) memset(x,y,sizeof(x))
#define out(x) printf(#x" %d\n", x)
#define sqr(x) ((x) * (x))
typedef long long lint;
const int maxint = -1u>>1;
const double eps = 1e-8;
const int maxn = 50 * 50 * 2 + 10;
const double pi = acos(-1.0);
int sgn(const double &x) { return (x > eps) - (x < -eps); }
struct point {
double x, y;
point (double _x = 0, double _y = 0) : x(_x), y(_y) {
}
void input() {
scanf("%lf%lf", &x, &y);
}
void output() {
printf("%.3f %.3f\n", x, y);
}
double len() const {
return sqrt(x * x + y * y);
}
point trunc (double l) const {
double r = l / len();
return point(x * r, y * r);
}
point rotate_left() const {
return point(-y, x);
}
point rotate_right() const {
return point(y, -x);
}
point rotate_left(double c) const {
double s = sqrt(1 - c * c);
return point(x * c - y * s, y * c + x * s);
}
point rotate_right(double c) const {
double s = sqrt(1 - c * c);
return point(x * c + y * s, y * c - x * s);
}
point set() {
double l = len();
return point(x / l, y / l);
}
bool operator < (const point &p) const {
if (sgn(p.x - x) != 0) return x < p.x;
else return y < p.y;
}
bool operator == (const point &p) const {
return sgn(x - p.x) == 0 && sgn(y - p.y) == 0;
}
double operator * (const point &p) const {
return (x * p.y) - (y * p.x);
}
double operator ^ (const point &p) const {
return (x * p.x) + (y * p.y);
}
point operator + (const point &p) const {
return point(x + p.x, y + p.y);
}
point operator - (const point &p) const {
return point(x - p.x, y - p.y);
}
point operator / (double mul) const {
return point(x / mul, y / mul);
}
};
vector<point> ogn, inter;
double rr[maxn];
int fa[maxn], sumv[maxn], sume[maxn];
int find(int w) {
if (fa[w] == w) return w;
int k = find(fa[w]);
sumv[k] += sumv[w];
sume[k] += sumv[w];
fa[w] = k;
return k;
}
void getInter(vector<point> &inter, int i, int j) {
if (rr[i] > rr[j]) swap (i, j);
double a = rr[i];
double b = rr[j];
double c = (ogn[i] - ogn[j]).len();
//printf("%.2f %.2f %.2f\n", b, a, c);
if (sgn(b - a - c) >= 0) {
return;
}
if (sgn(c - a - b) > 0) return;
else if (sgn(c - a - b) == 0) {
inter.push_back(ogn[i] + (ogn[j] - ogn[i]).trunc(a));
}
else {
double cs = (-b * b + a * a + c * c) / (2 * a * c);
point dir = (ogn[j] - ogn[i]).trunc(a);
inter.push_back(ogn[i] + dir.rotate_left(cs));
inter.push_back(ogn[i] + dir.rotate_right(cs));
//printf("%.2f %.2f\n", (inter.back() - ogn[j]).len(), b);
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
ogn.clear();
rep (i, n) {
point x;
x.input();
ogn.push_back(x);
scanf("%lf", &rr[i]);
}
inter.clear();
rep (i, n) {
repf (j, i + 1, n - 1) {
getInter(inter, i, j);
}
}
sort(inter.begin(), inter.end());
inter.erase(unique(inter.begin(), inter.end()), inter.end());
//printf("%d\n", sz(inter));
rep (i, sz(inter)) {
fa[i] = i;
sumv[i] = 1;
sume[i] = 0;
}
int ans = 1;
rep (i, n) {
//printf("%d : %d\n", i, ans);
vector<int> have;
rep (k, sz(inter)) {
//printf("%.2f %d %d\n", (ogn[i] - inter[k]).len() - rr[i], i, k);
if (sgn((ogn[i] - inter[k]).len() - rr[i]) == 0) {
//printf("%d\n", k);
have.push_back(k);
}
}
if (sz(have) == 0)
ans++;
else {
rep (j, sz(have))
repf (k, j + 1, sz(have) - 1) {
int r = find(have[j]);
int h = find(have[k]);
if (r != h) {
if (r > h) swap(r, h);
fa[h] = r;
sumv[r] += sumv[h];
sume[r] += sume[h];
}
}
int r = find(have[0]);
sume[r] += sz(have);
}
}
int v[maxn];
memset(v, 0, sizeof(v));
rep (i, sz(inter)) {
int r = find(i);
if (v[r] == 0) {
v[r] = 1;
//printf("%d %d \n", sume[r], sumv[r]);
ans += sume[r] - sumv[r] + 1;
}
}
printf("%d\n", ans);
}
return 0;
}
Problem D: LinearProgramming Dual
略
Solution
Tag:模拟
死做就行,做法题面告诉了。
/*
* Author: chlxyd
* Created Time: 2013/7/24 15:12:23
* File Name: D.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
char s1[20],s2[1100] ;
char ss[20] ;
char s[110][1100];
int ans[110] , jl[110] , bj[110] ;
int g[110][110] ;
int val[110] ;
int n , m , T ;
int type ;
void change1() {
if ( s1[1] == 'i' ) {
type = 0 ;
s1[1] = 'a' ;
s1[2] = 'x' ;
}
else {
type = 1 ;
s1[1] = 'i' ;
s1[2] = 'n' ;
}
}
void change2() {
s2[strlen(s2)+1] = 0 ;
s2[strlen(s2)] = '+' ;
int l = strlen(s2) ;
if ( s2[0] == 0 ) {
repf( i , 1 , n ) ans[i] = 0 ;
return ;
}
int sta = 0 , now[2] = {0} ;
int flag = 0 ;
rep( i , l ) {
char c = s2[i] ;
if ( c >= '0' && c <= '9' )
now[sta] = now[sta] * 10 + c - '0' ;
else if ( c == 'x' )
sta = 1 ;
else if ( c == '+' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 0 ;
ans[now[1]] = now[0] ;
now[0] = now[1] = 0 ;
sta = 0 ;
}
else if ( c == '-' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 1 ;
ans[now[1]] = now[0] ;
now[0] = now[1] = 0 ;
sta = 0 ;
}
}
}
void change( int i ) {
s[i][strlen(s[i])+1] = 0 ;
s[i][strlen(s[i])] = '+' ;
int l = strlen(s[i]) ;
if ( s[i][0] == 0 ) {
repf( j , 1 , n ) g[j][i] = 0 ;
val[i] = 0 ;
if ( s[i][1] == '=' ) {
jl[i] = 0 ;
repf( j , 2 , strlen(s[i]) - 2 )
val[i] = val[i] * 10 + s[i][j] - '0' ;
}
else if ( s[i][1] == '>' ) {
jl[i] = 1 ;
repf( j , 3 , strlen(s[i]) - 2 )
val[i] = val[i] * 10 + s[i][j] - '0' ;
}
else {
jl[i] = 2 ;
repf( j , 3 , strlen(s[i]) - 2 )
val[i] = val[i] * 10 + s[i][j] - '0' ;
}
return ;
}
int sta = 0 , now[3] = {0} ;
int flag = 0 ;
rep( j , l ) {
char c = s[i][j] ;
if ( c >= '0' && c <= '9' )
now[sta] = now[sta] * 10 + c - '0' ;
else if ( c == 'x' )
sta = 1 ;
else if ( c == '+' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
if ( flag) now[2] = - now[2] ;
flag = 0 ;
if ( sta == 2 )
val[i] = now[2] ;
g[now[1]][i] = now[0] ;
now[0] = now[1] = 0 ;
if ( sta == 1 )
sta = 0 ;
}
else if ( c == '-' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 1 ;
g[now[1]][i] = now[0] ;
now[0] = now[1] = 0 ;
if ( sta == 1)
sta = 0 ;
}
else if ( c == '>' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 0 ;
g[now[1]][i] = now[0] ;
now[0] = now[1] = 0 ;
jl[i] = 0 ;
j ++ ; jl[i] = 1 ;
sta = 2 ;
}
else if ( c == '<' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 0 ;
g[now[1]][i] = now[0] ;
now[0] = now[1] = 0 ;
jl[i] = 0 ;
j ++ ; jl[i] = 2 ;
sta = 2 ;
}
else if ( c == '=' ) {
if ( now[0] == 0 ) now[0] = 1 ;
if ( flag ) now[0] = - now[0] ;
flag = 0 ;
g[now[1]][i] = now[0] ;
now[0] = now[1] = 0 ;
jl[i] = 0 ;
sta = 2 ;
}
}
}
void did( int i ){
string str = (string) ss ;
if ( str.find('<') != string::npos ) {
bj[i] = 1 ;
}
else if ( str.find('>') !=string::npos ) {
bj[i] = 2 ;
}
else bj[i] = 0 ;
}
string c( int x ) {
if ( x == 0 ) return "0" ;
x = abs(x) ;
string ret = "" ;
while ( x ) {
ret = ret + (char)('0'+x % 10) ;
x /= 10 ;
}
reverse(ret.begin() , ret.end()) ;
return ret ;
}
string get1( int *val ) {
string ret = "" ;
repf( i , 1 , m ) {
if ( val[i] > 0 ) {
if ( ret != "" ) ret += '+';
if ( val[i] != 1 )
ret += c(val[i]) ;
ret += 'y' + c(i) ;
}
else if ( val[i] < 0 ) {
ret += '-' ;
if ( val[i] != -1 )
ret += c(val[i]) ;
ret += 'y' + c(i) ;
}
}
if ( ret == "" ) ret = '0' ;
return ret ;
}
string get2(int i) {
string ret = "" ;
ret = 'y' + c(i) ;
if ( type == 1 && jl[i] >= 1 )
jl[i] = 3 - jl[i] ;
if ( jl[i] == 1 ) ret += ">=0" ;
else if ( jl[i] == 2 ) ret += "<=0" ;
else ret += " arbitary" ;
return ret ;
}
string get3( int i , int *val ) {
string ret = get1(val) ;
if ( type == 1 && bj[i] >= 1 )
bj[i] = 3 - bj[i] ;
if ( bj[i] == 1 ) ret += ">=" ;
else if ( bj[i] == 2 ) ret += "<=" ;
else ret+= '=' ;
if ( ans[i] < 0 ) ret += '-' ;
ret += c(abs(ans[i])) ;
return ret ;
}
void show() {
printf("%d %d\n" , m , n ) ;
printf("%s " , s1 ) ;
printf("%s\n" , get1(val).c_str() ) ;
puts("with") ;
repf( i , 1 , m )
printf("%s\n" , get2(i).c_str() ) ;
puts("under") ;
repf( i , 1 , n )
printf("%s\n" , get3(i,g[i]).c_str()) ;
}
int main(){
//freopen("D.in","r",stdin);
scanf("%d" , &T ) ;
repf( t , 1 , T ) {
if ( t != 1 ) puts("") ;
clr(bj) ; clr(jl) ; clr(ans) ; clr(val) ; clr(g) ;
scanf("%d %d" , &n , &m ) ;
scanf("%s %s" , s1 , s2 ) ;
change1() ; change2() ;
scanf("%s\n" , ss ) ;
repf( i , 1 , n ) {
gets(ss) ;
did(i) ;
}
scanf("%s" , ss ) ;
repf( i , 1 , m ) {
scanf("%s" , s[i] ) ;
change(i) ;
}
show();
//return 0 ;
}
}
Problem E: DVD
一个人有个DVD播放器,有2000张DVD电影盘,每张盘有一个出厂时间和一个地区。先出厂的电影必须在后出场的电影之前看,也可以不看。 DVD刚开始可以设点一个地区,然后可以转换5次地区。
问最多可以看多少部电影。时间的范围只有200
Solution
Tag:DP
F[i][j]表示看完第I年的电影后,最后DVD的地区设置成J,转移时需要枚举下一年要看哪几个地区的电影和看完后最后DVD转到哪个地区。贪心出代价,然后转移。
/*
* Author: chlxyd
* Created Time: 2013/7/22 19:13:41
* File Name: E_chlxyd.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
int g[140][8][7][32][4] ;
int dp[140][8][7][32] ;
string name[2100] ;
vector<int> v[140][7] ;
vector<int> res ;
int jl[4];
int maxx , n , T ;
char s[110] ;
void clrr() {
clr(jl) ;
clr(g) ; clr(dp) ;
repf( i , 1 , 138 )
rep( j , 6 ) v[i][j].clear() ;
res.clear() ;
maxx = 0 ;
}
void add( int i , int k ) {
rep( j , v[i][k].size() ) {
res.push_back(v[i][k][j]) ;
}
}
void update( int &x , int y , int i , int j , int k , int s , int i1 , int j1 , int k1 , int s1 ) {
//printf("%d %d %d %d %d %d %d %d %d %d\n" , i , j , k , s , i1 , j1 , k1 , s , x , y ) ;
if ( j == 7 ) return ;
if ( x < y ) {
x = y ;
g[i][j][k][s][0] = i1 ;
g[i][j][k][s][1] = j1 ;
g[i][j][k][s][2] = k1 ;
g[i][j][k][s][3] = s1 ;
if ( maxx < x ) {
maxx = x ;
jl[0] = i ; jl[1] = j ; jl[2] = k ; jl[3] = s ;
}
}
}
void Dp() {
int all = (1<<5) ;
repf( k , 1 , 5 ) {
dp[1][1][k][1<<(k-1)] = v[1][k].size() ;
if ( maxx < v[1][k].size() ) {
maxx = v[1][k].size() ;
jl[0] = 1 ; jl[1] = 1 ; jl[2] = k ; jl[3] = 1<<(k-1) ;
}
}
repf( i , 1 , 2004 - 1869 ) {
repf( j , 1 , 6 )
repf( k , 1 , 5 )
rep( s , all ) {
repf( k1 , 1 , 5 ) {
if ( !(s&(1<<(k1-1))) ) {
update(dp[i][j+1][k1][s|(1<<(k1-1))] , dp[i][j][k][s] + v[i][k1].size() , i , j + 1 , k1 , s|(1<<(k1-1)) , i , j , k , s ) ;
}
else update(dp[i][j+1][k1][s] , dp[i][j][k][s] , i , j + 1 , k1 , s , i , j , k , s ) ;
}
update(dp[i+1][j][k][(1<<(k-1))] , dp[i][j][k][s] + v[i+1][k].size() , i + 1 , j , k , (1<<(k-1)) , i , j , k , s ) ;
}
}
//cout<<dp[2][2][2][3]<<endl;
}
void find_way( int i , int j , int k , int s ){
//cout<<i<<" "<<j<<" "<<k<<" "<<s<<endl;
int i1 = g[i][j][k][s][0] , j1 = g[i][j][k][s][1] , k1 = g[i][j][k][s][2] , s1 = g[i][j][k][s][3] ;
if ( i1 == 0 ) {
add(i,k) ;
return ;
}
if ( i != i1 )
add( i , k ) ;
else if ( j != j1 ) {
if ( !(s1&(1<<(k-1))) )
add( i , k ) ;
}
find_way( i1 , j1 , k1 , s1 ) ;
}
int main(){
//freopen("EE.out","w",stdout) ;
scanf("%d" , &T ) ;
repf( t , 1 , T ) {
if ( t != 1 ) puts("" ) ;
maxx = 0 ;
scanf("%d\n" , &n ) ;
clrr() ;
repf( i , 1 , n ) {
name[i].clear();
int sta = 0 ;
char c ;
while ( scanf("%c" , &c ) == 1 ) {
if ( c == '"' ) {
name[i] += c ;
sta ++ ;
if ( sta == 2 ) break ;
}
else {
if ( sta == 1 ) {
name[i] = name[i] + c ;
}
}
}
int y , p ;
scanf("%d %d" , &y , &p ) ;
y -= 1869 ;
//cout<<y<<p<<endl;
v[y][p].push_back(i) ;
}
Dp();
find_way(jl[0],jl[1],jl[2],jl[3]) ;
printf("%d\n" , res.size()) ;
reverse(res.begin(),res.end());
rep( i , res.size() )
printf("%s\n" , name[res[i]].c_str() ) ;
}
}
Problem F: ThinkPositive
Solution
Tag:数据结构
把每天的a值赋值一份丢到数组末尾,然后求前i项的和sum[i],那么sum[i]-sum[j]就是j+1~i天的a[i]总和,维护一个长度为n的集合,最开始把最后n个sum丢进去,然后队列往前移动,如果队列中最小值都大于sum[now],那么表示队列中所有天数的a[i]值和都为正,累加答案。
/*
* Author: chlxyd
* Created Time: 2013/7/22 13:59:10
* File Name: F.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
multiset<int> st ;
int n , T ;
int a[410000] ;
int sum[410000] ;
int main(){
repf ( t , 1 , 1 ) {
st.clear() ;
scanf("%d" , &n ) ;
int ans = 0;
repf( i , 1 , n ) scanf("%d" , &a[i] ) ;
repf( i , n + 1 , n + n - 1 ) a[i] = a[i-n] ;
repf( i , 1 , n + n - 1 ) sum[i] = sum[i-1] + a[i] ;
repd( i , n + n - 1 , n ) st.insert( sum[i] ) ;
repd( i , n - 1 , 1 ) {
if ( (*st.begin()) > sum[i] ) ans ++ ;
st.erase( sum[i+n] ) ;
st.insert( sum[i] ) ;
}
if ( (*st.begin()) > sum[0] ) ans ++ ;
printf("%d\n" , ans ) ;
}
}
Problem G: Ranking
略
Solution
Tag:模拟
死做。
/*
* Author: chlxyd
* Created Time: 2013/7/22 14:18:19
* File Name: G.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
#define maxn 110
int c[maxn] ;
int con_par[maxn] , R[maxn];
char s[maxn][110] ;
double Sij[maxn] , score[maxn] , RSij[maxn] ;
int n , T ;
struct teamtype {
int a[30] ;
int id ;
int time_use ;
int pro_solve ;
bool operator < ( const teamtype & q ) const {
if ( pro_solve != q.pro_solve )
return pro_solve > q.pro_solve ;
return time_use < q.time_use ;
}
}p[maxn] ;
struct ranktype {
int id ;
double score ;
bool operator < ( const ranktype &q ) const {
return score > q.score ;
}
}final[maxn] ;
void Did_contest() {
int tnum , pnum , rnum ;
scanf("%d" , &tnum ) ;
repf( i , 1 , tnum ) {
scanf("%d" , &p[i].id ) ;
c[p[i].id] = i ;
}
scanf("%d" , &pnum ) ;
repf( i , 1 , tnum ) {
p[i].time_use = p[i].pro_solve = 0 ;
repf( j , 1 , pnum )
p[i].a[j-1] = 0 ;
}
scanf("%d" , &rnum ) ;
repf( i , 1 , rnum ) {
int id , ti ;
char ps[2] , res[2] ;
scanf("%d %s %d %s" , &id , ps , &ti , res ) ;
id = c[id] ;
if ( res[0] == '+' ) {
if ( p[id].a[ps[0]-'A'] == 1 ) continue ;
p[id].time_use += ti - p[id].a[ps[0]-'A'] * 20 ;
p[id].pro_solve += 1 ;
p[id].a[ps[0]-'A'] = 1 ;
}
else if ( p[id].a[ps[0]-'A'] != 1 )
p[id].a[ps[0]-'A'] -- ;
}
sort( p + 1 , p + tnum + 1 ) ;
int A , B ;
B = tnum - 2 ; A = 2 + 2 * B ;
R[1] = 1 ;
repf( i , 2 , tnum ) {
if ( p[i].pro_solve == p[i-1].pro_solve && p[i].time_use == p[i-1].time_use )
R[i] = R[i-1] ;
else R[i] = i ;
}
repf( i , 1 , tnum ) {
if ( p[1].pro_solve == 0 ) RSij[i] = 0 ;
else RSij[i] = (double)p[i].pro_solve / p[1].pro_solve ;
Sij[i] = (double)RSij[i] * A / ( B + R[i] ) ;
con_par[p[i].id] ++ ;
score[p[i].id] += Sij[i];
}
}
void clrr() {
repf( i , 1 , n ) {
con_par[i] = 0 ;
score[i] = 0 ;
}
}
int main(){
scanf("%d" , &T ) ;
repf( t , 1 , T ) {
if ( t != 1 ) puts("") ;
scanf("%d\n" , &n ) ;
clrr() ;
int len = 0 ;
repf( i , 1 , n ) {
gets(s[i]) ;
len = max( len , (int)strlen(s[i]) ) ;
}
repf( i , 1 , n ) {
int nowlen = (int)strlen(s[i]) ;
while ( nowlen < len ) {
s[i][nowlen] = ' ' ;
s[i][nowlen+1] = 0 ;
nowlen = strlen(s[i]) ;
}
}
int m ;
scanf("%d" , &m ) ;
repf( i , 1 , m ) Did_contest() ;
repf( i , 1 , n ) {
final[i].id = i ;
if ( con_par[i] != 0 )
final[i].score = (double)score[i] / con_par[i] ;
else final[i].score = 0 ;
}
sort( final + 1 , final + n + 1 ) ;
repf( i , 1 , n )
printf("%s %.4lf\n" , s[final[i].id] , final[i].score ) ;
}
}
Problem H:
给个方格图,要求从起点起走最短路到终点。若有多条路可以走,按照几天贪心的规则走。输出方案。
Solution
Tag:最短路
SPFA求出重终点到任意点的最短路,然后若当前点在i,离终点的最短路为dis[i],下一步走的位置j的dis[j]一定需要等于dis[i] – 1,然后有多条路经的话安题目给的贪心规则走即可。
/*
* Author: chlxyd
* Created Time: 2013/7/22 12:57:33
* File Name: H.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
const int maxint = 1 << 29;
const int maxn = 400 + 10;
const int maxm = maxn * 2 + 10;
char s[maxm][maxm];
int bx[] = {-1, 0, 1, 0};
int by[] = {0, 1, 0, -1};
int dis[maxn * maxn * 4], v[maxn * maxn + 4];
int n, m, nm;
string ans;
queue<int> que;
int getId(int x, int y) {
x /= 2, y /= 2;
return x * m + y;
}
void getXY(int h, int &x, int &y) {
x = (int)(h / m) * 2;
y = (int)(h % m) * 2;
}
bool ok(int x, int y) {
return 0 <= x && x <= 2 * (n - 1) && 0 <= y && y <= 2 * (m - 1);
}
void spfa() {
rep (i, nm) {
dis[i] = maxint;
v[i] = 0;
}
int sx = (0) * 2, sy = (m - 1) * 2;
int h = getId(sx, sy);
v[h] = 1;
que.push(h);
dis[h] = 0;
while (!que.empty()) {
int h = que.front();
v[h] = 0;
que.pop();
int x, y;
getXY(h, x, y);
//printf("%d %d %d\n", x, y, dis[h]);
rep (i, 4) {
int dx = x + bx[i];
int dy = y + by[i];
int nx = x + 2 * bx[i];
int ny = y + 2 * by[i];
int nh = getId(nx, ny);
if (ok(dx, dy) && (s[dx][dy] == '|' || s[dx][dy] == '-') && dis[nh] > dis[h] + 1) {
//printf("%d %d %d %d\n", nx, ny, n, m);
dis[nh] = dis[h] + 1;
if (!v[nh]) {
v[nh] = 1;
que.push(nh);
}
}
}
}
}
char getDir(int d, int nd) {
//printf("%d %d\n", d, nd);
if (d == -1) {
if (nd == 0) return 'N';
else return 'E';
}
else {
if (d == nd) return 'F';
int tmp = (d + 1) % 4;
if (tmp == nd) return 'R';
else return 'L';
}
}
void getPath() {
ans.clear();
int dir = -1;
int x = (n - 1) * 2, y = 0;
while (x != 0 || y != (m - 1) * 2) {
int h = getId(x, y);
int ma = -1;
//printf("%d %d %d %d\n", x, y, dir, dis[h]);
rep (i, 4) {
int dx = x + bx[i];
int dy = y + by[i];
int nx = x + 2 * bx[i];
int ny = y + 2 * by[i];
int nh = getId(nx, ny);
if (ok(dx, dy) && (s[dx][dy] == '|' || s[dx][dy] == '-') && dis[nh] == dis[h] - 1) {
if (ma == -1 || ma != dir)
ma = i;
}
}
if (ma == -1) while(1);
x = x + bx[ma] * 2;
y = y + by[ma] * 2;
ans.push_back(getDir(dir, ma));
dir = ma;
}
}
int main(){
int T;
//scanf("%d", &T);
//rep (ca, T) {
//if (ca != 0) puts("");
scanf("%d%d\n", &n, &m);
nm = n * m;
rep (i, 2 * n - 1) {
gets(s[i]);
}
//rep (i, n)
//puts(s[i]);
//puts("");
spfa();
//puts("test");
getPath();
printf("%c\n", ans[0]);
repf (i, 1, sz(ans) - 1) {
printf("%c", ans[i]);
}
printf("\n");
//}
return 0;
}