100道动态规划——16 UVA 1627 Team them up! 二分图,背包,不过关键还是学会转化

来源:互联网 发布:太原java工程师 编辑:程序博客网 时间:2024/05/24 01:45

确实,这道题目只要知道怎么看之后就好写很多了,关键在于知道这样看。

判定每一个连通块是不是一个二分图,假若有一个不是的话,那就是无解。

一个连通块被划为二分图是唯一的嘛(反证法),然后就可以处理出两队,把这两队的人数之差作为一个物品。

这样最后的问题就变成了,在所有物品都必须拿的情况下,背包的价值最接近0。

那此时的状态就是“定义dp[i][j+n]代表前i件物品的价值之和是j的情况是不是存在”(注意可能为负)

用的是刷表法,因为这里的物品既可以加,也可以减。

判定二分图的代码我之前写过,不过和DP结合起来这倒是第一次。。恩。。

还是学会分析吧,积累经验。

#include <cstdio>#include <algorithm>#include <cstring>#include <vector>using namespace std;int t,n,arr[110],color[110],ti,dp[110][220],graph[110][110];vector<int> team[110][2];bool judge(),dfs(int now,int c);void dp_(),print(int ans);int main(){scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=0,te;i<n;++i)while(scanf("%d",&te)&&te)graph[i][te-1]=1;if(!judge())printf("No solution\n");else dp_();printf("\n");memset(graph,0,sizeof graph);}return 0;}void dp_(){memset(dp,0,sizeof dp);dp[0][n]=1;for(int i=1;i<=ti;++i)for(int j=-n;j<=n;++j)if(dp[i-1][j+n])dp[i][j+arr[i-1]+n]=dp[i][j-arr[i-1]+n]=1;for(int i=0;i<=n;++i)if(dp[ti][i+n])print(i),i=n+1;else if(dp[ti][-i+n])print(i),i=n+1;}void print(int ans){//printf("aaaaaaaaaaa\n");vector<int> team1,team2;for(int i=ti-1;i>=0;--i){if(dp[i][ans-arr[i]+n]){ans-=arr[i];for(int j=team[i][1].size()-1;j>=0;--j)team1.push_back(team[i][1][j]);for(int j=team[i][0].size()-1;j>=0;--j)team2.push_back(team[i][0][j]);}else{ans+=arr[i];for(int j=team[i][0].size()-1;j>=0;--j)team1.push_back(team[i][0][j]);for(int j=team[i][1].size()-1;j>=0;--j)team2.push_back(team[i][1][j]);}}printf("%d",team1.size());for(int i=0;i<team1.size();++i)printf(" %d",team1[i]+1);printf("\n");printf("%d",team2.size());for(int i=0;i<team2.size();++i)printf(" %d",team2[i]+1);printf("\n");}bool judge(){memset(color,0,sizeof color);ti=0;for(int i=0;i<n;++i){if(!color[i]){team[ti][0].clear();team[ti][1].clear();if(!dfs(i,1))return false;arr[ti]=team[ti][0].size()-team[ti][1].size();++ti;}}return true;}bool dfs(int now,int c){color[now]=c;team[ti][c-1].push_back(now);for(int v=0;v<n;++v)if(now!=v&&!(graph[now][v]&&graph[v][now])){if(color[v]==c)return false;else if(!color[v]&&!dfs(v,3-c))return false;}return true;}


0 0
原创粉丝点击