2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)
D.Distinctive Character
看到樣例,第一個反應貪心。先寫了個按這一位1和0的數目多少,確定0還是1的東西。感覺不夠真,又寫了個盡量加到相似的比較小的串上的貪心。在和前邊的那個組合一下,換了換順序。。。好吧就過了13組樣例。。。正解如下:考慮如何求出,所有2^k個狀態與這n個串的最大相似度。起初的n個串的答案顯然為k,那改變一個位置,相似度就改變為k-1,對于一個狀態,越早算出來的相似度,越大,那么就可以直接bfs求出所有狀態的最大相似度了。答案就是取最小值的狀態。
#include <bits/stdc++.h> #define mem(W) memset(W,0,sizeof(W)) using namespace std; int n, k, a[1<<23], b[1<<23]; char s[25]; int q[1<<23],l=0,r=0; int main(){scanf("%d%d",&n,&k);for(int i=0;i<(1<<k);++i)b[i]=-1;for(int i=1;i<=n;++i) {scanf(" %s",s);for(int j=0;j<k;++j) a[i]=a[i]*2+(s[j]-'0');q[r]=a[i];++r;b[a[i]]=k;}while(l<r){int S=q[l]; ++l;for(int i=0;i<k;++i){if(b[S^(1<<i)]==-1){b[S^(1<<i)]=b[S]-1;q[r]=S^(1<<i); ++r;}}}int MN=10000,ans=0;for(int i=0;i<(1<<k);++i){if(MN>b[i]){MN=b[i];ans=i;}}for(int i=k-1;i>=0;--i)printf("%d",!!(ans&(1<<i)));puts(""); }E.Emptying the Baltic?
bfs暴搜的做法很顯然,一直搜到所有位置都無法流向周圍的格子為止,但是會tle??紤]剪枝:1)水位低的地方,不能流向高的地方;2)沒有水也不能流了;3)最重要的一個剪枝/貪心,我們盡量先去從當前水位比較高的地方搜,用優先隊列可以解決。(讀題能力好差。。。
#include <cstdio> #include <queue> #define rep(i,a,b) for(int i=a;i<=b;++i) typedef long long ll; const int N = 550; inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } using namespace std; int dx[]={0, 0, 1, 1, -1, -1, 1, -1}; int dy[]={1,-1, 0,-1, 0, 1, 1, -1}; int n, m, xs, ys; ll mp[N][N], h[N][N]; struct node{int x,y;bool operator < (const node a) const {return h[a.x][a.y] < h[x][y];}node(){}node(int a,int b){x=a;y=b;} }; inline int inb(int x,int y) {if(x>n||x<1||y>m||y<1)return 0;return 1; } inline ll solve(node e,node s){ll t;if(mp[s.x][s.y] >= h[e.x][e.y]) {t=h[s.x][s.y]-mp[s.x][s.y];h[s.x][s.y]-=t;return t;}else {t=h[s.x][s.y]-h[e.x][e.y];h[s.x][s.y]-=t;return t;}return t; }inline ll bfs(int sx, int sy) {ll ans=0;priority_queue<node> q;q.push(node(sx,sy));ans += (-mp[sx][sy]);h[sx][sy]=mp[sx][sy];while(!q.empty()) {node u=q.top();q.pop();rep(i,0,7) {int tx=u.x+dx[i], ty=u.y+dy[i];if(!inb(tx,ty)||mp[tx][ty]>=0||h[tx][ty] <= h[u.x][u.y])continue;if(h[tx][ty]==mp[tx][ty]) continue;ll tmp=solve(u,node(tx,ty));ans+=tmp;q.push(node(tx,ty));}}return ans; } int main() {n=read(),m=read();rep(i,1,n)rep(j,1,m)mp[i][j]=read();xs=read(),ys=read();printf("%lld\n", bfs(xs,ys)); }G.?Galactic Collegiate Programming Contest
用數據結構維護比1隊排名靠前的隊伍。一眼考慮用優先隊列加數組標記,感覺刪除的復雜度就沒有保證,狀態本身就多,還額外加了一些,肯定會T,就沒寫。然后,考慮用set刪除操作就很方便,然而還是T了。(于是膜了題解。。。還學了很多神奇的操作%%%)用multiset的話,有很多重復的值,時間就更優秀了。
#include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) const int N = 1e5 + 100; typedef long long ll; using namespace std; struct node{int x,y;node(){}node(int a,int b){x=a;y=b;}bool operator < (const node a)const {if(a.y!=y) return y > a.y;return x < a.x;} }; multiset<node> s; int n,m,t,p,a[N],b[N]; int main() {scanf("%d%d",&n,&m);rep(i,1,m) {scanf("%d%d",&t,&p);if(t!=1) {if(node(a[t],b[t]) < node(a[1],b[1])) s.erase(s.find(node(a[t],b[t])));a[t]+=p;++b[t];s.insert(node(a[t],b[t]));}else {a[t]+=p;++b[t];}while(!s.empty()&&!(*--s.end()<node(a[1],b[1]))) s.erase(--s.end());printf("%d\n",s.size()+1);} }?
轉載于:https://www.cnblogs.com/RRRR-wys/p/9086143.html
總結
以上是生活随笔為你收集整理的2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenAI首批投资者科斯拉:大多数AI
- 下一篇: BZOJ5358: [Lydsy1805