比賽地址:http://codeforces.com/contest/362python
參考連接:http://codeforces.com/blog/entry/9584#comment-150925ios
我不喜歡CF的題的一個緣由是它的題意太"複雜「,並且有"反人類"傾向。(笑數組
本題中就有一個表述:ide
After the meeting the semiknights can move on, so it is possible that they meet again.函數
初看此題的人可能會忽略這個細節,可是這個此題巧妙解法的一個關鍵。編碼
先說通常解法spa
分別用BFS(or DFS)求出騎士A和騎士B所能到達的位置以及到達位置時的時間。code
若是A和B都能到達maze[i][j] != ‘#’,且時間爲Ta和Tb。blog
若是(Ta - Tb) % 2 == 0時,則能夠達成meeting條件,反之不能夠。(若是一個騎士先到達位置,則能夠重複來回跳從而湊足步數。)排序
再說巧妙解法:
由於移動規則的限制,每一輪兩個騎士的相對位置只會有以下幾種狀況:x + 4 or x - 4 or y + 4 or y - 4 or 不變
因此若是(A.x - B.x) % 4 == 0 || (A.y - B.y) % 4 == 0,則能夠肯定A和B能夠到達同一點,但這一點能夠不爲'#'。
若是A和B到達了某一個'#'點,根據上面的條件(meet again),則咱們能夠反推A或B到達該點的路徑,到達A或B的出生點,從而知足條件。
簡單題。只須要查找有沒有i, i+1, i+2均爲dirty stairs的就能夠了。
坑點:
題意很扭曲。簡單表示就是,給你一個序列,讓你作插入排序。排序前給你一個機會讓你交換兩個數的位置,使插入排序使用swap函數的次數最少。請問有幾種交換方法,此時使用swap函數的次數是多少。
易得,插入排序使用swap的次數等於序列的逆序數。因此咱們交換的目的是減小逆序數。
咱們枚舉pair(A[i], A[j]),且i < j。此時對於逆序數的變化值爲 (A[i+1 ... j-1]中小於j的數的個數) + (A[i+1 ... j-1]中大於i的個數)
這個統計可使用樹狀數組來解決。不詳細說了。(樹狀數組 - Wiki)
又是一道題意抽風題。大概題意就是一個國家,分紅n個區域,區域之間不聯通(也不電信^_^)。如今想用p條路鏈接區域,將這n個區域連爲q個區域。鏈接兩個區域的代價是: min(10^9, S + 1)。S是鏈接的兩個區域中的路徑長度之和。
坑:
int可能會溢出,不過不影響最後結果。
min(10^9, S + 1)中的 +1
若是A~B已經有一條路徑,咱們還能夠新建A~B的路徑,且花費爲1000。(用來湊足路徑數的關鍵。這個條件太扭曲了!怒吐一槽!)
若是簡化題意和坑,這題就是一個比較簡單的Huffman編碼的變種。可是加上這些坑和限制,就有的折騰了。
一個明顯的最小費用流。小小的處理一下費用上界就能夠了。
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define print(x) cout << x << endl #define input(x) cin >> x const size_t N = 8; struct Point { int x,y; Point(){} Point(int ix, int iy): x(ix), y(iy){} }; char maze[N+5][N+5]; int main() { freopen("input.txt", "r", stdin); int T; input(T); while (T--) { for (int i = 0; i < (int)N; i++) { scanf("%s", maze[i]); } int p = 0; Point ks[2]; for (int i = 0; i < (int)N; i++) { for (int j = 0; j < (int)N; j++) { if (maze[i][j] == 'K') { ks[p++] = Point(i, j); } } } int dy = ks[0].y - ks[1].y; int dx = ks[0].x - ks[1].x; puts(dy % 4 == 0 && dx % 4 == 0? "YES" : "NO"); } return 0; }
(n, m) = map(int, raw_input().split()) if m: dirties = sorted(map(int, raw_input().split())) if not m: print 'YES' elif (dirties[0] == 1 or dirties[-1] == n): print 'NO' else: for i in xrange(m): p = dirties[i:i+3] if (len(p) != 3): continue else: if p[0] == p[1] - 1 == p[2] - 2: print 'NO' break else: print 'YES'
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define print(x) cout << x << endl #define input(x) cin >> x const int SIZE = 5120; const int INF = 0x3f3f3f3f; inline int lowbit(int x) { return x&(-x); } struct BIT//點更新,區間查詢 { int baum[SIZE]; inline void init() { memset(baum,0,sizeof(baum)); } void add(int x,int val) { while(x<SIZE) { baum[x]+=val; x+=lowbit(x); } } int sum(int x) { int res=0; while(x>0) { res+=baum[x]; x-=lowbit(x); } return res; } int sum(int a,int b)//查詢區間和 { return sum(b)-sum(a-1); } }; int n; int A[SIZE]; int main() { freopen("input.txt", "r", stdin); BIT bit; input(n); for (int i = 0; i < n; i++) { input(A[i]); A[i]++; } int ans = -INF; int ans_cnt = -1; for (int i = 0; i < n; i++) { bit.init(); bit.add(A[i], 1); for (int j = i + 1; j < n; j++) { int adv = 0; bit.add(A[j], 1); adv -= bit.sum(0, A[j] - 1); adv += bit.sum(A[j] + 1, n); adv += bit.sum(0, A[i] - 1); adv -= bit.sum(A[i] + 1, n); if (adv == ans) { ans_cnt++; } else if (adv > ans) { ans = adv; ans_cnt = 1; } } } int inv = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { if (A[j] > A[i]) { inv++; } } } print(inv - ans + 1<< ' ' << ans_cnt); return 0; }
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <bitset> #include <set> #include <queue> #include <map> using namespace std; #define print(x) cout << x << endl #define input(x) cin >> x typedef long long llint; const int SIZE = 100100; const llint INF = 1000000000LL; struct Road { int from, to; llint cost; Road(){} Road(int ifrom, int ito, llint icost): \ from(ifrom), to(ito), cost(icost) {} }; struct Distinct { int nr; llint tot; Distinct(){} Distinct(int inr, llint itot): \ nr(inr), tot(itot){} friend bool operator < (const Distinct& a, const Distinct& b) { return a.tot > b.tot; } }; int n, m, p ,q; vector<Road> road_vec, new_road_vec; int cnc[SIZE]; llint rlen[SIZE]; void init() { road_vec.clear(); new_road_vec.clear(); for (int i = 0; i < SIZE; i++) { cnc[i] = i; } memset(rlen, 0, sizeof(rlen)); } int get_father(int x) { if (cnc[x] == x) return x; else return cnc[x] = get_father(cnc[x]); } int make_union() { for (int i = 0;i < (int)road_vec.size(); i++) { int from = road_vec[i].from; int to = road_vec[i].to; cnc[get_father(from)] = cnc[get_father(to)]; } set<int> st; for (int i = 0; i < n; i++) { st.insert(get_father(cnc[i])); } return st.size(); } void fill_rlen() { for (int i = 0; i < (int)road_vec.size(); i++) { int from = road_vec[i].from; int cost = road_vec[i].cost; rlen[get_father(from)] += cost; } } llint solve() { llint res = 0; priority_queue<Distinct> pq; for (int i = 0; i < n; i++) { if (get_father(i) != i) continue; else { pq.push(Distinct(i, rlen[i])); } } for (int i = 0; i < p && pq.size() >= 2; i++) { Distinct a = pq.top(); pq.pop(); Distinct b = pq.top(); pq.pop(); llint cost = min(INF, a.tot + b.tot + 1); res += cost; new_road_vec.push_back(Road(a.nr, b.nr, -1)); Distinct c(a.nr, a.tot + b.tot + cost); pq.push(c); } return res; } int main() { freopen("input.txt", "r", stdin); int a, b; llint c; while(input(n >> m >> p >> q)) { init(); while (m--) { input(a >> b >> c); a--;b--; road_vec.push_back(Road(a, b, c)); } int us = make_union(); fill_rlen(); if (us - p > q || us < q) { print("NO"); continue; } llint ans = 0; int t = 0; bool need_fill = false; Road road_fill; if (us - p < q) { t = p - (us - q); p = us - q; need_fill = true; } ans += solve(); if (need_fill && \ road_vec.empty() && new_road_vec.empty()) { print("NO"); continue; } else if (need_fill) { road_fill = !road_vec.empty()? road_vec[0]: new_road_vec[0]; } print("YES"); for (int i = 0; i < t; i++) { new_road_vec.push_back(road_fill); } ans += 1000 * t; for (int i = 0; i < (int)new_road_vec.size(); i++) { printf("%d %d\n", new_road_vec[i].from + 1, new_road_vec[i].to + 1); } //print(ans); } return 0; }
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> using namespace std; #define print(x) cout << x << endl #define input(x) cin >> x const int NODE = 1024; const int EDGE = 180000; const int INF = 0x3f3f3f3f; struct edge { int dest, flow, cost, next; edge(){} edge(int idest, int iflow, int icost, int inext): \ dest(idest), flow(iflow), cost(icost), next(inext){} }; edge g[EDGE]; int ind; int head[NODE],pre[NODE]; int dis[NODE]; char visit[NODE]; int n, K; inline void _addEdge(int st,int end,int flow,int cost) { g[ind]=edge(end,flow,cost,head[st]); head[st]=ind++; } inline void addEdge(int st,int end,int flow,int cost) { _addEdge(st,end,flow,cost); _addEdge(end,st,0,-cost); } void init() { memset(head,-1,sizeof(head)); ind=0; } int spfa(int source,int sink) { queue<int> q; memset(dis,0x3f,sizeof(dis)); memset(visit,0,sizeof(visit)); pre[source]=-1; q.push(source); visit[source]=1; dis[source]=0; while(!q.empty()) { int now=q.front(); q.pop(); visit[now]=0; for(int i=head[now];i!=-1;i=g[i].next) { int next=g[i].dest; int cost=g[i].cost; int flow=g[i].flow; if(flow>0 && dis[next]>dis[now]+cost) { dis[next]=dis[now]+cost; if(!visit[next]) { q.push(next); visit[next]=1; } pre[next]=i; } } } return dis[sink]; } void MinCostMaxFlow(int source, int sink, int &maxflow, int &mincost) { int flow; maxflow = 0; mincost = 0; while(1) { int cost = spfa(source, sink); if(cost >= INF) break; flow = INF; int now = sink; while(now != source) { flow = min(flow, g[pre[now]].flow); now = g[pre[now] ^ 1].dest; } if (mincost + flow * cost > K) { maxflow += (K - mincost) / cost; break; } maxflow += flow; mincost += flow * cost; now = sink; while(now != source) { g[pre[now]].flow -= flow; g[pre[now] ^ 1].flow += flow; now = g[pre[now] ^ 1].dest; } } } int main() { freopen("input.txt","r", stdin); int a; input(n >> K); init(); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { input(a); if (a) { addEdge(i, j, a, 0); addEdge(i, j, K, 1); } } } int flow, cost; MinCostMaxFlow(1, n, flow, cost); print(flow); return 0; }