• ZOJ3951 : Independent Set


    如果知道了树的形态,那么可以树形DP,每个时刻只需要计算必选根的独立集个数以及必不选根的独立集个数。

    那么现在知道独立集个数,要构造出树,可以考虑DP这棵树的形态,然后将之前树形DP的值作为现在DP的状态,即$dp[i][j]$表示必选根的独立集个数为$i$,必不选根的独立集个数为$j$时,树的节点数最少是多少。

    那么完成这个DP之后,输出方案只需要沿着最优值来的顺序dfs输出即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    const int Inf=100;
    int cnt;
    int dp[2020][2020];
    struct Node{
    	short i,j,x,y;
    	Node(){}
    	Node(short i,short j,short x,short y):i(i),j(j),x(x),y(y){}
    };
    Node pre[2020][2020];
    void dfs(int u,int x,int y){
    	if(x==1&&y==1)return ;
    	//printf("x=%d y=%d
    ",x,y);
    	dfs(u,pre[x][y].i,pre[x][y].j);
    	++cnt;
    	printf("%d %d
    ",u,cnt);
    	dfs(cnt,pre[x][y].x,pre[x][y].y);
    }
    vector<int>V[3000];
    int main(){
    	int tl=0;
    	for(int i=1;i<=2005;i++){
    		for(int j=i;j<=2005;j+=i)V[j].push_back(i);
    	}
    	for(int i=0;i<2020;i++)for(int j=0;j<2020;j++)dp[i][j]=Inf;
    	dp[1][1]=1;
    	for(int i=1;i<=2005;i++){
    		for(int j=1;j<=2005;j++){
    			if(dp[i][j]>15)continue;
    			for(int y=1;y*i<=2005;y++){
    				for(int x=1;(x+y)*j<=2005;x++){
    					int tmp=dp[i][j]+dp[x][y];
    					int nx=y*i,ny=j*(x+y);
    					if(dp[nx][ny]>tmp){
    						dp[nx][ny]=tmp;
    						pre[nx][ny]=Node(i,j,x,y);
    					}
    					tl++;
    				}
    			}
    			for(int y=1;y*(i+j)<=2005;y++){
    				for(int x=1;x*j<=2005;x++){
    					int tmp=dp[i][j]+dp[x][y];
    					int nx=j*x,ny=y*(i+j);
    					if(dp[nx][ny]>tmp){
    						dp[nx][ny]=tmp;
    						pre[nx][ny]=Node(x,y,i,j);
    					}
    					tl++;
    				}
    			}
    
    		}
    	}
    	/*
    	for(int nx=1;nx<=2005;nx++){
    		for(int ny=1;ny<=2005;ny++){
    			if(nx==1&&ny==1){dp[nx][ny]=1;continue;}
    			for(int it1=0;it1<V[nx].size();it1++){
    				for(int it2=0;it2<V[ny].size();it2++){
    					int i=V[nx][it1],j=V[ny][it2];
    					int y=nx/i,x=ny/j-y;
    					if(x>=1&&y>=1&&dp[i][j]+dp[x][y]<dp[nx][ny]){
    						dp[nx][ny]=dp[i][j]+dp[x][y];
    						pre[nx][ny]=Node(i,j,x,y);
    					}
    					tl++;
    				}
    			}
    		}
    	}
    	*/
    	//printf("tl=%d
    ",tl);
    	int _;scanf("%d",&_);
    	while(_--){
    		int m;
    		scanf("%d",&m);
    	//for(int tm=1;tm<=2000;tm++){
    	//	m=tm+1;
    		m++;
    		bool flag=0;
    		int sx=-1,sy;
    		for(int i=0;i<=m;i++){
    			if(dp[i][m-i]<=15){
    				sx=i;sy=m-i;
    				break;
    			}
    		}
    		if(sx<0)puts("-1");
    		else{
    			printf("%d
    ",dp[sx][sy]);
    			cnt=1;
    			dfs(1,sx,sy);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Visual Studio Code的常用快捷键
    requests模块
    爬虫基本原理
    Django-分页、中间件和请求的声明周期
    Django-admin管理工具
    Django-form表单
    Django-认证系统
    cookie、session和token
    Ajax
    Django进阶Model篇—数据库操作(ORM)
  • 原文地址:https://www.cnblogs.com/clrs97/p/6686935.html
Copyright © 2020-2023  润新知