標籤:style blog http color strong os
本來應該認真做這場的,思路都是正確的。
C題,是先該橫切完或豎切完,無法滿足刀數要求,再考慮橫切+豎切(豎切+橫切),
因為橫切+豎切(或豎切+橫切)會對切割的東西產生交叉份數,從而最小的部分不會儘可能的大。
代碼如下,雖然比較長、比較亂,但完全可以壓縮到幾行,因為幾乎是4小塊重複的代碼,自己也懶得壓縮
注意一點,比如要判斷最小塊的時候,比如9行要分成2份,最小的剩下那份不是9模數2,而應該是4
m/(k+1)<=m-m/(k+1)*k
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAX = 1e6+10;const LL MOD = 1e9+7;LL f[1000];int main() { LL n,m,k; //freopen("in.txt", "r", stdin); while(scanf("%I64d %I64d %I64d",&n,&m, &k)==3) { if(k > (n+m-2)) { printf("-1\n"); continue;} LL k1 = k; LL ans = 0, ans2 = 0; if(1){ if(k<=(m-1)){ if(m%(k+1)==0) ans = m/(k+1)*n; else if(m/(k+1)<=m-m/(k+1)*k) { ans = m/(k+1)*n; } else ans = (m/(k+1)-1)*n; } else { k -= (m-1); if(n%(k+1)==0) ans = n/(k+1); else if(m/(k+1)<=m-m/(k+1)*k) { ans = n/(k+1); } else ans = (n/(k+1)-1); } } //printf("%I64d~\n", ans); swap(n, m); if(2){ k = k1; if(k<=(m-1)){ if(m%(k+1)==0) { ans2 = m/(k+1)*n; } else if(m/(k+1)<=m-m/(k+1)*k) { ans2 = m/(k+1)*n; } else ans2 = (m/(k+1)-1)*n; } else { k -= (m-1); if(n%(k+1)==0) ans2 = n/(k+1); else if(m/(k+1)<=m-m/(k+1)*k) { ans2 = n/(k+1); } else ans2 = (n/(k+1)-1); } } printf("%I64d\n", max(ans, ans2)); }}
D題
一看題目時就很欣喜,挺有意思的圖論。
一開始的思路是錯的,每次進行鬆弛操作時判斷當前邊是否標記過,從而進行減減操作,這樣考慮忘了後面可能進行了一些更新,從而覆蓋了前面的標記
正確思路:
在每次優先隊列出點的時候,判斷從起點到這個點的最短路有多少是跟K條(train route)是重複的即可
自己需要注意的地方:
1、怎樣記錄最短路的數目
2、當k==Count[u]時候的處理
3、小細節,第一個節點u,tt與Count[u]都是等於0的
代碼還是挺快的~
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;#define clr(x) memset(x,0,sizeof(x))#define fp1 freopen("in.txt","r",stdin)#define fp2 freopen("out.txt","w",stdout)#define pb push_back#define INF 0x3c3c3c3ctypedef long long LL;const int maxn = 4*1e5;bool vis[maxn];struct Edge {int from,to,dist,cnt;};struct Node{ int d,u; bool operator <(const Node &a) const { return a.d<d; //從小到大排序。 }};int n,m,k; //點數和邊數,用n表示,e不能和m衝突vector<Edge> edges;//邊列表vector<int> G[maxn];//每個結點出發的邊編號(從0開始編號)vector<int> qw[maxn];int Count[maxn];bool done[maxn];//是否已永久編號int d[maxn];//s到各個點的距離int p[maxn];//最短路中的上一條邊void init(){ for(int i=0;i<n;i++) G[i].clear();//清空鄰接表 edges.clear();}void addedge(int from,int to,int dist)//如果是無向,每條無向邊需調用兩次addedge{ edges.push_back((Edge){from,to,dist}); int temp=edges.size(); G[from].push_back(temp-1);}void dijk(int s){ clr(Count); priority_queue<Node> q; for(int i=0;i<n;i++) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); q.push((Node){0,s}); while(!q.empty()) { Node x=q.top(); q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int i=0;i<G[u].size();i++) { Edge &e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; q.push((Node){d[e.to],e.to}); Count[e.to] = 1; } else if(d[e.to]==d[u]+e.dist){ Count[e.to] ++; } } int tt = 0; for(int i = 0;i < qw[u].size();i++){ if(qw[u][i] > d[u]) { //printf("%d %d %d~\n", u, qw[u][i], d[u]); int temp = k -1; k = temp; } else if(qw[u][i] == d[u]) tt++; } //printf("%d %d %d!\n", u, tt, Count[u]); if(tt == 0) continue; else if(tt < Count[u]) { k -= tt; } else if(tt == Count[u]) k -= (tt-1); }}int main(){ //fp1; while(scanf("%d %d %d", &n, &m, &k) == 3){ int k1 = k; init(); int u, v, w; for(int i = 1;i <= m;i++){ scanf("%d %d %d", &u, &v, &w); u--; v--; addedge(u, v, w); addedge(v, u, w); } for(int i = m+1;i <= m+k;i++){ scanf("%d %d", &u, &v); u--; addedge(0, u, v); addedge(u, 0, v); qw[u].pb(v); } dijk(0); printf("%d\n", k1 - k); } return 0;}