1. 程式人生 > 其它 >do NOT a=2b (DP)

do NOT a=2b (DP)

swjtu—春季集訓 - Virtual Judge (vjudge.net)

題目:NEVER,NEVER,NEVER have a = 2ba=2b in an array!,刪最小的數目,滿足條件

思路:

  • 開始想用貪心給每一個點賦一個權值,在用優先佇列--修改版本,去解決
  • 發現改了,很多次,大資料過不了
  • 於是換思路,發現和DP有線性地推關係, 1,2, 4,8,16, 選與不選問題。
  • 當然還有 其他的 3,6,12 啥的,沒有2倍關係的就不管
  • 具體看程式碼
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define
M 2000005 template <class G> void read(G &x) { x=0;int f=0;char ch=getchar(); while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } int n; int p[M]; int dp[M][3]; int
num[M]; int vis[M]; int ans; void dfs(int a) { vis[a]=1; if(num[a*2]==0) return ; dp[a][1]=0; dp[a][0]=num[a]; a=a*2; while(1) { vis[a]=1; dp[a][1]=dp[a/2][0]; dp[a][0]=min(dp[a/2][0],dp[a/2][1])+num[a]; if(num[a*2]==0) { ans+=min(dp[a][1
],dp[a][0]); break; } a=a*2; } } int main(){ read(n); for(ri i=1;i<=n;i++) { read(p[i]); num[p[i]]++; } sort(p+1,p+1+n); for(ri i=1;i<=n;i++) { if(vis[p[i]]) continue; dfs(p[i]); } printf("%d",ans); }
View Code