在poj上刷30道DP

听说30道dp可以入门??。。。。

1.poj-1015

http://poj.org/problem?id=1015

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define N 201
#define M 21
using namespace std;
struct node {
	int d;
	int p;
	int sum;
	int dff;
}num[N];
int dp[N][M][801];
int re[N][M][801];
int main() {
	int n, m;
	int t = 1;
	while (1) {
		scanf("%d%d", &n, &m);
		if (n == m && n == 0)
			break;
		for (int i = 1; i <= n; i++) {
			scanf("%d%d", &num[i].p, &num[i].d);
			num[i].sum = num[i].p + num[i].d;
			num[i].dff = num[i].p - num[i].d;
		}
		int mid = 400;
		memset(dp, -1, sizeof(dp));
		memset(re, -1, sizeof(re));
		for (int i = 0; i <= n; i++) {
			dp[i][0][mid] = 0;
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m && j <= i; j++) {
				for (int k = 0; k <= mid*2; k++) {
					dp[i][j][k] = dp[i - 1][j][k];
					re[i][j][k] =re[i - 1][j][k];
					if (k - num[i].dff >= 0 && dp[i - 1][j - 1][k - num[i].dff] != -1)
					{
						if (dp[i][j][k] < dp[i - 1][j - 1][k - num[i].dff] + num[i].sum)
						{
							dp[i][j][k] = dp[i - 1][j - 1][k - num[i].dff] + num[i].sum;
							re[i][j][k] = i;
							//cout << dp[i][j][k] <<" "<<i<<" "<<j<<" " <<k<<endl;
						}
					}
				}
			}
		}
		int sumd = 0, sump = 0;
		int ans = 0;
		int a[100];
		for (int i = 0; i <= mid; i++) {
			if (dp[n][m][mid - i] != -1 || dp[n][m][mid + i] != -1) {
				if (dp[n][m][mid - i] > dp[n][m][mid + i]) {
					int k = mid - i;
					while (1) {
						int ps = re[n][m][k];
						//cout << ps << " " << n << " " << m << " " << k << endl;
						a[ans++] = ps;
						sump = sump + num[ps].p;
						sumd = sumd + num[ps].d;
						k = k - num[ps].dff; m--;
						n = ps - 1;
						if (m == 0)
							break;
					}
				}
				else {
					int k = mid + i;
					while (1) {
						int ps = re[n][m][k];
						//cout << ps <<" "<<n<<" "<<m<<" "<<k<< endl;
						a[ans++] = ps;
						sump = sump + num[ps].p;
						sumd = sumd + num[ps].d;
						k = k - num[ps].dff;m--;
						n=ps-1;
						if (m == 0)
							break;
					}
				}
				cout << "Jury #" << t++ << endl;
				cout << "Best jury has value " << sump << " for prosecution and value " << sumd << " for defence:" << endl;
				for (int i = ans-1; i >= 0; i--) {
					cout << " " << a[i];
				}
				cout << endl;
				break;
			}
		}
	}
	return 0;
}

2,poj-1035-DFS

http://poj.org/problem?id=1035

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
string DFS(string str) {
	if (str=="01")
		return str;
	else
	{
		string strs = "";
		vector<string> s;
		int start = 0, end, cnt = 0;
		str=str.substr(1, str.size() - 2);
		//cout << str << endl;
		for (int i = 0; i < str.length(); i++) {
			if (str[i] == '0')
				cnt++;
			else
			{
				cnt--;
				if (cnt == 0) {
					end = i;
					//cout << i << endl;
					s.push_back(DFS(str.substr(start, end - start + 1)));
					//cout << str.substr(start, end - start + 1);
					start = i + 1;
				}
			}
		}
		sort(s.begin(), s.end());
		strs += "0";
		for (int i = 0; i < s.size(); i++) {
			strs += s[i];
		}
		strs += "1";
		return strs;
	}
}
int main() {
	int n;
	scanf("%d", &n);
	while (n--) {
		string s1, s2;
		cin >> s1 >> s2;
		if (s1.length() != s2.length())
		{
			cout << "different" << endl;
			continue;
		}
		s1 = "0" + s1 + "1";
		s2 = "0" + s2 + "1";
		//cout << "s" << endl;
		s1 = DFS(s1);
		s2 = DFS(s2);
		if (s1 == s2)
			cout << "same" << endl;
		else
			cout << "different" << endl;
	}
	return 0;
}

3,poj-1636

http://poj.org/problem?id=1636

DFS+DP解决

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define N 205
using namespace std;
int t;
int n, m;
int anum, bnum;
int map[N][N];
int dp[N][N];
int vis[2][N];
void DFS(int side, int t) {
	vis[side][t] = 1;
	if (side == 0) {
		anum++;
		for (int i = 1; i <= n; i++) {
			if (map[t][i] && !vis[1][i]) {
				DFS(1, i);
			}
		}
	}
	else
	{
		bnum++;
		for (int i = 1; i <= n; i++) {
			if (map[i][t] && !vis[0][i]) {
				DFS(0, i);
			}
		}
	}
}
int main() {
	scanf("%d", &t);
	while (t--) {
		memset(map, 0, sizeof(map));
		memset(dp, 0, sizeof(dp));
		memset(vis, 0, sizeof(vis));
		scanf("%d%d", &n, &m);
		for (int i = 0; i < m; i++) {
			int x, y;
			scanf("%d%d", &x, &y);
			map[x][y] = 1;
		}
		int a[N], b[N];
		int k = 0;
		
		for (int i = 1; i <= n; i++) {
			if (vis[0][i])continue;
			anum = 0;
			bnum = 0;
			DFS(0, i);
			a[k] = anum;
			b[k++] = bnum;
		}
		for (int i = 1; i <= n; i++) {
			
			if (vis[1][i])continue;
			anum = 0;
			bnum = 0;
			DFS(1, i);
			a[k] = anum;
			b[k++] = bnum;
		}
		dp[0][0] = 1;
		for (int i = 0; i < k; i++) {
			for (int j = n / 2; j >= a[i]; j--) {
				for (int h = n / 2; h >= b[i]; h--) {
					if (dp[j][h]||dp[j - a[i]][h - b[i]] == 1) {
						dp[j][h] = 1;
					}
				}
			}
		}
		for (int i = n / 2; i >= 0; i--) {
			if (dp[i][i] == 1)
			{
				cout << i << endl;
				break;
			}
		}
	}
}

并查集+DP解决:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>p
#define N 205
using namespace std;
int t;
int p[2*N];
int find(int x) {
	if (x != p[x]) {
		p[x] = find(p[x]);
	}
	else
	return x;
}
void build(int x, int y) {
	int xx = find(x);
	int yy = find(y);
	if (xx != yy) {
		p[xx] = yy;
	}
}
void init(int n)
{
	for (int i = 1; i <= 2 * n; i++) {
		p[i] = i;
	}
}
int main() {
	int x, y, n, ks;
	scanf("%d", &t);
	while (t--) {
		int a[N];
		int b[N];
		int sum[2 * N];
		int dp[N / 2][N / 2];
		memset(dp, 0, sizeof(dp));
		dp[0][0] = 1;
		memset(a, 0, sizeof(a));
		memset(sum, 0, sizeof(sum));
		memset(b, 0, sizeof(b));
		scanf("%d%d", &n, &ks);
		init(n);
		for (int i = 0; i < ks; i++) {
			scanf("%d%d", &x, &y);
			build(x, y + n);
		}
		int ans = 1;
		for (int i = 1; i <= n; i++)
		{
			int x = find(i);
			if (sum[x] == 0) {
				sum[x] = ans++;
				a[sum[x]]++;
			}
			else
			{
				a[sum[x]]++;
			}
		}
		for (int i = n + 1; i <= 2 * n; i++)
		{
			int x = find(i);
			if (sum[x] == 0) {
				sum[x] = ans++;
				b[sum[x]]++;
			}
			else
			{
				b[sum[x]]++;
			}
		}
		for (int i = 1; i < ans; i++) {
			for (int j = n / 2; j >= a[i]; j--) {
				for (int k = n / 2; k >= b[i]; k--) {
					if (dp[j][k]||dp[j - a[i]][k - b[i]] == 1) {
						dp[j][k] = 1;
					}
				}
			}
		}
		for (int i = n / 2; i >= 0; i--) {
			if (dp[i][i] == 1)
			{
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
}

4,poj-1671 DP 递归 第二类斯特林数(Stirling)

http://poj.org/problem?id=1671

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
#define N 105
double dp[N][N];
int main() {
	int n;
	while (~scanf("%d", &n) && n != 0) {
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++) {
			dp[i][1] = 1;
		}
		dp[0][0] = 1;
		double sum = 0;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				dp[i][j] = dp[i - 1][j - 1] + j*dp[i - 1][j];
			}
		}
		for (int i = 1; i <= n; i++) {
			sum += dp[n][i];
		}
		printf("%d %.0f\n", n, sum);
	}
	return 0;
}

5,poj-1682 多重DP

大佬题解http://www.cnblogs.com/proverbs/archive/2012/10/03/2711151.html

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define N 102
#define inf 999999
int n, m, k;
int xz[N][N], xy[N][N], yz[N][N];
int x[N], y[N], z[N];
void init() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			xz[i][j] = inf;xy[i][j] = inf;yz[i][j] = inf;
		}
	}
}
void solve() {
	xy[n + 1][0] = 0;
	for (int i = n; i >= 1; i--) {
		for (int j = 1; j <= m; j++) {
			xy[i][j] = min(min(xy[i + 1][j - 1], xy[i + 1][j]), xy[i][j - 1]) + abs(x[i] - y[j]);
		}
	}
	xz[0][k + 1] = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = k; j >= 1; j--) {
			xz[i][j] = min(min(xz[i - 1][j + 1], xz[i - 1][j]), xz[i][j + 1]) + abs(x[i] - z[j]);
		}
	}
	yz[m + 1][0] = 0;
	for (int i = m; i >= 1; i--) {
		for (int j = 1; j <= k; j++) {
			yz[i][j] = min(min(yz[i + 1][j - 1], yz[i + 1][j]), yz[i][j - 1]) + abs(y[i] - z[j]);
		}
	}
	int ans = inf;
	for (int i = 0; i <= n + 1; i++) {
		for (int j = 0; j <= m + 1; j++) {
			for (int h = 0; h <= k + 1; h++) {
				//cout << xy[i][j] <<" "<<xz[i][h]<<" "<<yz[j][h]<< endl;
				ans = min(ans, xy[i][j] + xz[i][h] + yz[j][h]);
				ans = min(ans, xy[i + 1][j] + xz[i][h] + yz[j][h]);
				ans = min(ans, xy[i][j] + xz[i][h] + yz[j + 1][h]);
				ans = min(ans, xy[i][j] + xz[i][h + 1] + yz[j][h]);
				ans = min(ans, xy[i + 1][j] + xz[i][h] + yz[j + 1][h]);
				ans = min(ans, xy[i + 1][j] + xz[i][h + 1] + yz[j][h]);
				ans = min(ans, xy[i][j] + xz[i][h + 1] + yz[j + 1][h]);
				ans = min(ans, xy[i + 1][j] + xz[i][h + 1] + yz[j + 1][h]);
			}
		}
	}
	cout << ans << endl;
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		init();
		scanf("%d%d%d", &n, &m, &k);
		for (int i = 0; i < n; i++)
			scanf("%d", &x[i + 1]);
		for (int i = 0; i < m; i++)
			scanf("%d", &y[i + 1]);
		for (int i = 0; i < k; i++)
			scanf("%d", &z[i + 1]);
		solve();
	}
	return 0;
}

6,poj-1471 

并查集+dp

http://poj.org/problem?id=1417

给你p1个好人和p2个坏人,编号为1-p1+p2,然后给你n中操作

                   x1 x2 no:x1说x2不是好人

 

                  x1 x2 yes:x1说x2是好人

在这里好人说的总是对的,坏人说的总是坏的,然后问你最后能不能唯一确定哪些是好人,并输出,否则输出”no“
dp[i][j]:前i个大集合的好人数为j的方案数。如果dp[i(max)][p1]=1意味着能确定哪些是好人。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<map>
#include<functional>
#define N 1005
using namespace std;
int n, p1, p2;
int p[N];
int ranks[N];
int bs[N];
int dp[N][N];
int bg[N][N];
int fs[N];
int ans = 1;
struct cmp {
	bool operator()(int x,int y) {
		return x > y;
	}
};
set<int> q;
map<int, int>Q;
int find(int x)
{
	if (x != p[x]) {
		int temp = p[x];
		p[x] = find(p[x]);
		ranks[x] = (ranks[x] + ranks[temp]) % 2;
	}
	return p[x];
}
void build(int x1, int x2, string trag)
{
	int xx = find(x1);
	int yy = find(x2);
	if (xx != yy) {
		p[yy] = xx;
		if (trag == "no")
			ranks[yy] = (ranks[x2] - ranks[x1] + 3) % 2;
		else
			ranks[yy] = (ranks[x2] - ranks[x1] + 2) % 2;
	}
}
void init()
{
	q.clear();
	Q.clear();
	memset(dp, 0, sizeof(dp));
	memset(bg, 0, sizeof(bg));
	ans = 1;
	for (int i = 1; i <= p1 + p2; i++) {
		p[i] = i;
		ranks[i] = 0;
	}
}
void inster(int x,int v) {
	if (q.count(x)) {
		bg[fs[x]][v]++;
	}
	else
	{
		bs[ans] = x;
		fs[x] = ans++;
		bg[fs[x]][v]++;
		q.insert(x);
	}
}
int main()
{
	priority_queue<int, vector<int>, cmp > ps;
	string trag;
	int x1, x2;
	while (1)
	{
		scanf("%d%d%d", &n, &p1, &p2);
		if (n == p1 && p1 == p2 && n == 0)
			break;
		init();
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d", &x1, &x2);
			cin.get();
			cin >> trag;
			build(x1, x2, trag);
		}
		for (int i = 1; i <= p1 + p2; i++)
		{
			int f = find(i);
			inster(f, ranks[i]);
		}
		dp[0][0] = 1;
		for (int i = 1; i < ans; i++) {
			for (int j = 0; j <= p1; j++) {
				if (j >= bg[i][0])
					dp[i][j] = dp[i - 1][j - bg[i][0]];
				if(j>=bg[i][1])
					dp[i][j] += dp[i - 1][j - bg[i][1]];
			}
		}
		if (dp[ans - 1][p1] == 1) {
			int re = p1;
			for (int i = ans-1; i >= 1; i--) {
				if (dp[i-1][re - bg[i][0]] == dp[i][re])
				{
					re = re - bg[i][0];
					Q[bs[i]] = 0;
				}
				else
				if (dp[i-1][re - bg[i][1]] == dp[i][re])
				{
					re = re - bg[i][1];
					Q[bs[i]] = 1;
				}
			}
			for (int i = 1; i <= p1 + p2; i++) {
				int re = find(i);
				if (ranks[i] == Q[re])
				{
					ps.push(i);
				}
			}
			while (!ps.empty()) {
				cout << ps.top() << endl;
				ps.pop();
			}
			cout << "end" << endl;
		}
		else
			cout << "no" << endl;
	}
	return 0;
}

未完待续。。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值