zoukankan      html  css  js  c++  java
  • 将军令:贪心算法

    当然如果你想像考场上傻掉的我一样打树上dp,那祝你码得愉快了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define set(p) memset(dp[p],0x3f,sizeof(dp[p]))
     4 int dp[100005][5][5],n,fir[100005],l[200005],to[200005],cnt,k,p;
     5 void connect(int a,int b){
     6     l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
     7     l[++cnt]=fir[b];fir[b]=cnt;to[cnt]=a;
     8 }
     9 void dfs(int p,int f){
    10     for(int ii=fir[p];ii;ii=l[ii])if(to[ii]!=f)dfs(to[ii],p);
    11     int t=100002,tt=100003;set(t);memset(dp[t],0,sizeof(dp[t]));dp[t][0][0]=1;
    12     for(int ii=fir[p];ii;ii=l[ii])if(to[ii]!=f){
    13         t^=1;tt^=1;set(t);
    14         for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)
    15             dp[t][0][0]=min(dp[t][0][0],dp[tt][0][0]+dp[to[ii]][i][j]);
    16         for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)
    17             for(int x=0;x<=k+1;++x)for(int y=0;y<=k;++y) if(x+j<=k&&i+y<=k)
    18                 dp[t][min(i,x+1)][max(j,y+1)]=min(dp[t][min(i,x+1)][max(j,y+1)],dp[tt][i][j]+dp[to[ii]][x][y]);
    19         for(int i=0;i<=k+1;++i)for(int j=0;j<k;++j)dp[t][i][j+1]=min(dp[t][i][j+1],dp[t][i][j]);
    20         for(int i=0;i<=k;++i)for(int j=0;j<=k;++j)dp[t][i+1][j]=min(dp[t][i+1][j],dp[t][i][j]);
    21     }
    22     for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)dp[p][i][j]=dp[t][i][j];
    23     for(int i=0;i<=k+1;++i)for(int j=0;j<k;++j)dp[p][i][j+1]=min(dp[p][i][j+1],dp[p][i][j]);
    24     for(int i=0;i<=k;++i)for(int j=0;j<=k;++j)dp[p][i+1][j]=min(dp[p][i+1][j],dp[p][i][j]);
    25 }
    26 int main(){
    27     scanf("%d%d%d",&n,&k,&p);
    28     for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),connect(a,b);
    29     dfs(1,0);int ans=0x3f3f3f3f;
    30     for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)ans=min(ans,dp[1][i][j]);
    31     printf("%d
    ",ans);
    32 }
    先交的40分。只能处理k=1的树上dp
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define set(p) memset(dp[p],0x3f,sizeof(dp[p]))
     4 int dp[100005][11][11],n,fir[100005],l[200005],to[200005],cnt,k,p;
     5 void connect(int a,int b){
     6     l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
     7     l[++cnt]=fir[b];fir[b]=cnt;to[cnt]=a;
     8 }
     9 void dfs(int p,int f){
    10     for(int ii=fir[p];ii;ii=l[ii])if(to[ii]!=f)dfs(to[ii],p);
    11     int t=100002,tt=100003;set(t);dp[t][k][0]=0;dp[t][0][0]=1;
    12     for(int ii=fir[p];ii;ii=l[ii])if(to[ii]!=f){
    13         t^=1;tt^=1;set(t);
    14         for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)
    15             dp[t][0][0]=min(dp[t][0][0],dp[tt][0][0]+dp[to[ii]][i][j]);
    16         for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)
    17             for(int x=0;x<=k+1;++x)for(int y=0;y<=k;++y) if(x+j<=k&&i+y<=k)
    18                 dp[t][min(i,x+1)][max(j,y+1)]=min(dp[t][min(i,x+1)][max(j,y+1)],dp[tt][i][j]+dp[to[ii]][x][y]);
    19         for(int i=0;i<=k+1;++i)for(int j=0;j<k;++j)dp[t][i][j+1]=min(dp[t][i][j+1],dp[t][i][j]);
    20         for(int i=0;i<=k;++i)for(int j=0;j<=k;++j)dp[t][i+1][j]=min(dp[t][i+1][j],dp[t][i][j]);
    21     }
    22     for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)dp[p][i][j]=dp[t][i][j];
    23     for(int i=0;i<=k+1;++i)for(int j=0;j<k;++j)dp[p][i][j+1]=min(dp[p][i][j+1],dp[p][i][j]);
    24     for(int i=0;i<=k;++i)for(int j=0;j<=k;++j)dp[p][i+1][j]=min(dp[p][i+1][j],dp[p][i][j]);
    25 }
    26 int main(){
    27     scanf("%d%d%d",&n,&k,&p);
    28     for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),connect(a,b);
    29     dfs(1,0);int ans=0x3f3f3f3f;
    30     for(int i=0;i<=k+1;++i)for(int j=0;j<=k;++j)ans=min(ans,dp[1][i][j]);
    31     printf("%d
    ",ans);
    32     for(int i=1;i<=n;++i){printf("%d:
    ",i);
    33         for(int j=0;j<=k+1;++j){for(int x=0;x<=k;++x)printf("%d ",dp[i][j][x]==0x3f3f3f3f?-8:dp[i][j][x]);puts("");}
    34         puts("");
    35     }
    36 }
    盖掉它的0分代码(没删调试语句)实际上是20分)

    当然贪心这种东西除非会证明不然是真的不敢打。上次的T1就没发现那是一个贪心然而证明了正确性。。。

    当然这次根本没有往那个方向上去想。

    这个写的太好了。我无法反驳(因为它就是对的)

    所以,就没了!

    我们只需要维护一个数组f,表示从这个点开始多大的范围内能都被控制。

    那么我们在一个新的位置上设置守卫时这个位置的f就是k

    尝试更新与它相邻的点,它们的f在已有的f和k-1中取max就好。

    然后同理继续向外扩散就好了。初值要赋成-1,那么f!=-1就表示这个点已经被看守了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 priority_queue<pair<int,int> >q;
     4 int res[100005],cnt,n,k,t,fir[100005],l[200005],to[200005],f[100005],ans;
     5 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     6 void pre_dfs(int p,int fa,int dep){
     7     q.push(make_pair(dep,p));res[p]=-1;f[p]=fa;
     8     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)pre_dfs(to[i],p,dep+1);
     9 }
    10 void dfs(int p){
    11     for(int i=fir[p];i;i=l[i])if(res[to[i]]<res[p]-1)
    12         res[to[i]]=res[p]-1,dfs(to[i]);
    13 }
    14 int main(){
    15     scanf("%d%d%d",&n,&k,&t);
    16     for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y),link(x,y),link(y,x);
    17     pre_dfs(1,0,1);
    18     while(!q.empty()){
    19         int p=q.top().second;q.pop();if(res[p]>=0)continue;
    20         for(int i=1;i<=k;++i)if(f[p])p=f[p];
    21         res[p]=k;dfs(p);ans++;
    22     }
    23     printf("%d
    ",ans);
    24 }
    773B的小东西
  • 相关阅读:
    JVM调优
    【转】中文分词之HMM模型详解
    xwiki enterprise 8.4.5使用https步骤
    dubbo和shiro的整合,在服务端做权限验证
    电商课题:分布式锁
    Export large data from Gridview and Datareader to an Excel file using C#
    sap学习笔记
    git拉取远程分支并创建本地分支
    Echarts 解决饼图文字过长重叠的问题
    用localStorage坚持Vuex状态----vuex-persistedstate
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11335266.html
Copyright © 2011-2022 走看看