zoukankan      html  css  js  c++  java
  • POJ 1112 Team them up

    这学期第一篇博客,啊啊啊,罪过啊,O(∩_∩)O哈哈~

    这个题比较复杂:图论结合了简单的DP。

    直接还没办法求,需要找到反图,然后才能找到思路!

    解题思路:
    1.给出有向图,求出无向图,然后根据无向图求出反图
    2.DFS求出各一个连通分量,并给每一个连通分量染色
    3.DP求出最优状态,并记录路径
    详细过程:DP为了求出所有的状态-----也就是在分完第k个连通分量之前(当然是从第1个连通分量开始分的)的所有可能的状态,当分完最后一个连通分量时,就是n个人中所能分出的所有状态!!
    即f[i][j]表示未分第k个连通分量时的所有状态!则有:
    if(f[i][j]==1 && f[i+cnt[k][0]][j+cnt[k][1]]==0) f[i+cnt[k][0]][j+cnt[k][1]]=1;
    if(f[i][j]==1 && f[i+cnt[k][1]][j+cnt[k][0]]==0) f[i+cnt[k][1]][j+cnt[k][0]]=1;
    更重要的一点是:得记录路径用pre[i][j]结构体,记录前一个的i,j;记录从前一个状态到这个状态i和j上都加了什么?即记录加的是哪个k的哪一部分(0 & 1)!

    #include <iostream>
    
    using namespace std;
    
    const int MAXN=101;
    
    struct Record
    {
    	int i,j;
    	int id,is;
    }pre[MAXN][MAXN];
    
    int map[MAXN][MAXN],n;
    int dp[MAXN][MAXN];
    int cnt[MAXN][2];
    int dataPtr[MAXN][2],data[MAXN],next[MAXN],ind;
    //int color[MAXN];
    int flag[MAXN];
    
    
    void addedge(int id,int is,int u)
    {
    	data[ind]=u;
    	next[ind]=dataPtr[id][is];
    	dataPtr[id][is]=ind;
    
    	ind++;
    }
    
    bool DFS(int v,int id,int is)
    {
    	cnt[id][is]++;
    	flag[v]=is;
    	addedge(id,is,v);
    
    	for(int u=1;u<=n;u++)
    	{
    		if(map[v][u])
    		{
    			if(flag[u]==-1)
    			{
    				if(DFS(u,id,!is))	return true;
    			}		
    			else if(flag[v]==flag[u])
    				return true;
    		}
    	}
    	
    	return false;
    }
    
    void solve()
    {
    
    	int i , j , k , l , id ;
    	cin>>n;
    
    	//求出反图
    	memset(map,0,sizeof(map));
    	for(i=1;i<=n;i++)
    	{
    		cin>>j;
    	//	while(j) { map[i][j]=1; }	调试①
    		while(j) { map[i][j]=1; cin>>j; }
    	}
    
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<i;j++)
    		{
    			if(map[i][j]==1 && map[j][i]==1)
    				map[i][j]=map[j][i]=0;
    			else	map[i][j]=map[j][i]=1;
    		}
    	}
    	////////////
    
    	///DFS得到连通分量并染色
    	memset(flag,-1,sizeof(flag));
    //	memset(cnt,0,sizeof(cnt));
    //	memset(dp,0,sizeof(dp));
    	memset(dataPtr,-1,sizeof(dataPtr)); ind=0;
    
    	//调试②:id没有赋值
    	
    	id=0;
    	for(i=1;i<=n;i++)
    	{
    		if(flag[i]==-1)
    		{
    			if(DFS(i,++id,0))
    			{
    				cout<<"No solution"<<endl;
    				return ;
    			}
    		}
    	}
    
    	///DP记录路径并得到结果
    	int num=0;	dp[0][0]=1;
    	for(k=1;k<=id;k++)
    	{
    		for(i=0;i<=num;i++)
    		{
    			j=num-i;
    			if(dp[i][j]==1)
    			{
    				int nexti,nextj;
    				for(l=0;l<2;l++)
    				{
    					nexti=i+cnt[k][l];	nextj=j+cnt[k][!l];
    					if(dp[nexti][nextj]==0)
    					{
    						dp[nexti][nextj]=1;
    						pre[nexti][nextj].i=i;
    						pre[nexti][nextj].j=j;
    						pre[nexti][nextj].id=k;
    						pre[nexti][nextj].is=l;
    					}
    				}
    			}
    		}
    		num+=cnt[k][0]+cnt[k][1];
    	}
    	for(i=n/2,j=n-i; ;i--,j++)
    	{
    		if(dp[i][j])	
    		{
    			break;
    		}
    	}
    
    	///输出结果
    	int ind[2]={0,0};
    	cnt[0][0]=i;	cnt[0][1]=j;
    	while(i || j)
    	{
    		int id=pre[i][j].id;
    		int is=pre[i][j].is;
    		for(int l=0;l<2;l++,is=!is)
    		{
    			for(int k=dataPtr[id][is];k!=-1;k=next[k])
    			{
    				cnt[++ind[l]][l]=data[k];
    			}
    		}
    		int tmp=i;
    		i=pre[i][j].i;	j=pre[tmp][j].j;
    	}
    
    	for(i=0;i<2;i++)
    	{
    		cout<<cnt[0][i];	
    		for(j=1;j<=cnt[0][i];j++)
    			cout<<" "<<cnt[j][i];
    		cout<<endl;
    	}
    	
    }
    
    
    
    int main()
    {
    	freopen("input.txt","r",stdin);
    	
    	solve();
    
    	return 0;
    }
    

      

  • 相关阅读:
    P1383 高级打字机
    P1383 高级打字机
    P3723 [AH2017/HNOI2017]礼物 [FFT]
    P3723 [AH2017/HNOI2017]礼物 [FFT]
    P3338 [ZJOI2014]力 [FFT]
    P3338 [ZJOI2014]力 [FFT]
    P2597 [ZJOI2012]灾难
    c语言推箱子 扫雷项目
    蓝桥杯c语言基础题
    c语言的图形库
  • 原文地址:https://www.cnblogs.com/fornever/p/2375203.html
Copyright © 2011-2022 走看看