poj 1112 uva1627

状态是前i个能凑到的与j最相近的数。


/*test case
1
5
2 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0


*/
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
#define INF 100000000
using namespace std;

const int maxn = 100 + 5, mid = 103;
int head[maxn], V[maxn*maxn], skip[maxn*maxn], L, N;
bool G[maxn][maxn],mark[maxn][2*maxn];
int adjient[maxn], R, vis[maxn],d[maxn][2*maxn];
struct Nima {
  int id, type;
  Nima(int id, int type) : id(id), type(type) {}
};
vector<Nima> liantong[maxn];

// simple judge
bool pd(int J) {
    if(J<2*maxn && J >= 0) return true;
    return false;
}
bool opt(int j, int u, int o) {
  j -= mid;
  if(abs(o-j) < abs(u-j)) return true; 
  return false;
}

void init() {
  memset(d, 0, sizeof(d));
  memset(G, 0, sizeof(G));
  L = -1;
  memset(head, -1, sizeof(head));
  memset(vis, 0, sizeof(vis));
  for(int i = 0; i <= R; i++) liantong[i].clear();
  R = 0;
}

bool dfs(int dot, int& num) {
  num+=vis[dot];
  liantong[R].push_back(Nima(dot, vis[dot])); 
  for(int u = head[dot]; u != -1; u = skip[u])
  {
    if(!vis[V[u]]) {
	  vis[V[u]] = -vis[dot];
	  if(!dfs(V[u], num)) return false;
	}else if(vis[V[u]] == vis[dot]) return false;
  }
  return true;
}

int main() {
	int k;
	init();
	scanf("%d",&N);
	for(int i = 1; i <= N; i++) {
	  int x;
	  while(scanf("%d",&x)==1 && x) G[i][x] = 1;
	}
	for(int i = 1; i <= N; i++)
	  for(int j = i+1; j <= N; j++)
	{
	  if(!G[i][j] || !G[j][i]) {
		V[++L] = j; skip[L] = head[i]; head[i] = L;
		V[++L] = i; skip[L] = head[j]; head[j] = L;
	  }
	}
	bool wrong = 0;
	for(int i = 1; i <= N; i++) {
	  if(!vis[i]) {
	    ++R;
		vis[i] = 1;
		k = 0;
		if(!dfs(i,k)){wrong = 1; break;}
		adjient[R] = k;
	  }
	}
	/*
	//test 
	for(int i = 1; i <= R; i++) {
	  printf("liantong %d: ",i);
	  for(int j = 0; j < liantong[i].size(); j++) {
	    printf("%d ",liantong[i][j].id);
	  }
	  putchar('\n');
	}
	*/
	
	if(wrong) {printf("No solution\n");return 0; }
	
	//d[0][0~maxn*2-1] = 0;
	for(int i = 1; i <= R; i++) {
	  for(int j = 0; j < 2*maxn; j++) {
	    d[i][j] = INF;
	    if(pd(j-adjient[i]) && opt(j, d[i][j], d[i-1][j-adjient[i]]+adjient[i]) ) {
	      d[i][j] = d[i-1][j-adjient[i]] + adjient[i];// we choose to add
	      mark[i][j] = 1;
		}
		if(pd(j+adjient[i]) && opt(j, d[i][j], d[i-1][j+adjient[i]]-adjient[i]) ) {
	      d[i][j] = d[i-1][j+adjient[i]]-adjient[i]; // we choose to reduce
	      mark[i][j] = 0;
		}
	  }
	}
	vector<int> left, right;       // 1 for left, -1 for right; when mark is 0, we turn around ;
	for(int i = R, now = mid; i>=1; i--) {
	  if(mark[i][now]) {
	    for(int U = 0; U < liantong[i].size(); U++) {
	      Nima& K = liantong[i][U];
	      if(K.type == 1) left.push_back(K.id);
	      else right.push_back(K.id);
		}
		now -= adjient[i];
	  } else {
	    for(int U = 0; U < liantong[i].size(); U++) {
	      Nima& K = liantong[i][U];
	      if(K.type == -1) left.push_back(K.id);
	      else right.push_back(K.id);
		}
		now += adjient[i];
	  }
	}
	printf("%d",left.size()); sort(left.begin(), left.end());
	for(vector<int>:: iterator tat = left.begin(); tat != left.end(); ++tat) {
	  printf(" %d",*tat);                    
	}
	printf("\n");
	printf("%d",right.size()); sort(right.begin(), right.end());
	for(vector<int>:: iterator tat = right.begin(); tat != right.end(); ++tat) {
      printf(" %d",*tat);
	}	
	printf("\n");
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值