在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;
}

未完待续。。。。

猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/83062492