usaco6.1.1 Postal Vans

该博客介绍了ACM南太平洋地区2003年的题目——Postal Vans。问题涉及计算一个有N条南北街道的矩形网格郊区中,从邮局出发经过每个交叉路口恰好一次并返回邮局的不同路线数量。博客内容包括原题描述、输入输出格式、示例及代码实现,最终展示了一个成功的AC(Accepted)结果。

一 原题

Postal Vans

ACM South Pacific Region -- 2003

Tiring of their idyllic fields, the cows have moved to a new suburb. The suburb is a rectangular grid of streets with a post office at its Northwest corner. It has four avenues running East-West and N (1 <= N <= 1000) streets running North-South.

For example, the following diagram shows such a suburb with N=5 streets, with the avenues depicted as horizontal lines, and the post office as a dark blob at the top-left corner:

Each day the postal van leaves the post office, drives around the suburb and returns to the post office, passing exactly once through every intersection (including those on borders or corners). The executives from the post company want to know how many distinct routes can be established for the postal van (of course, the route direction is significant in this count).

For example, the following diagrams show two such routes for the above suburb:

As another example, the following diagrams show all the four possible routes for a suburb with N=3 streets:

Write a program that will determine the number of such distinct routes given the number of streets.

PROGRAM NAME: vans

INPUT FORMAT

  • Line 1: A single integer, N

SAMPLE INPUT (file vans.in)

4

OUTPUT FORMAT

  • Line 1: A single integer that tells how many possible distinct routes corresponding to the number of streets given in the input.

SAMPLE OUTPUT (file vans.out)

12


二 分析

给定任意图,求哈密顿回路是NPC的。但是由于这道题的图有一定特殊性,因此可以用动态规划解决。具体解释:http://www.docin.com/p-94253938.html

要手写大整数。


三 代码

运行结果:

USER: Qi Shen [maxkibb3]
TASK: vans
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 5160 KB]
   Test 2: TEST OK [0.000 secs, 5160 KB]
   Test 3: TEST OK [0.000 secs, 5160 KB]
   Test 4: TEST OK [0.000 secs, 5160 KB]
   Test 5: TEST OK [0.000 secs, 5160 KB]
   Test 6: TEST OK [0.000 secs, 5160 KB]
   Test 7: TEST OK [0.000 secs, 5160 KB]
   Test 8: TEST OK [0.000 secs, 5160 KB]
   Test 9: TEST OK [0.000 secs, 5160 KB]
   Test 10: TEST OK [0.000 secs, 5160 KB]
   Test 11: TEST OK [0.014 secs, 5160 KB]

All tests OK.

Your program ('vans') produced all correct answers! This is your submission #6 for this problem. Congratulations!


AC代码:

/*
ID:maxkibb3
LANG:C++
PROB:vans
*/

#include<cstdio>
#include<cstring>
#include<algorithm>

struct BigInteger {
	char s[500];
	
	BigInteger() { memset(s, 0, sizeof(s)); }

	BigInteger(int _n) {
		memset(s, 0, sizeof(s));
		int len = 0;
		char t[500];
		if(_n == 0) {
			s[0] = '0'; return;
		}
		while(_n != 0) {
			t[len++] = _n % 10 + '0';
			_n = _n / 10;
		}
		for(int i = 0; i < len; i++)
			s[i] = t[len - 1 - i];
	}

	BigInteger operator + (const BigInteger &_o) const {
		BigInteger ret;
		int len1 = std::max(strlen(_o.s), strlen(s)),
			len2 = std::min(strlen(_o.s), strlen(s));
		bool flag = false;
		for(int i = 0; i < len1; i++) {
			int tmp = (_o.s[i] - '0' + s[i] - '0') + flag;
			if(i >= len2) tmp += (int)'0';
			ret.s[i] = tmp % 10 + '0';
			if(tmp >= 10) flag = true;
			else flag = false;
		}
		if(flag) ret.s[len1] = '1';
		return ret;
	}

	BigInteger operator - (const BigInteger &_o) const {
		BigInteger ret;
		int len1 = std::max(strlen(_o.s), strlen(s)),
			len2 = std::min(strlen(_o.s), strlen(s));
		bool flag = false;
		for(int i = 0; i < len1; i++) {
			int tmp = s[i] - _o.s[i] - flag;
			if(i >= len2) tmp -= '0';
			ret.s[i] = (tmp + 10) % 10 + '0';
			if(tmp < 0) flag = true;
			else flag = false;
		}
		// ganrantee _o is smaller
		if(flag) ret.s[len1 - 1]--;
		return ret;
	}

	void operator = (const BigInteger &_o) {
		memcpy(s, _o.s, sizeof(_o.s));
	}

	BigInteger multi_2() const {
		BigInteger ret;
		int len = strlen(s);
		bool flag = false;
		for(int i = 0; i < len; i++) {
			int tmp = (s[i] - '0') * 2 + flag;
			ret.s[i] = tmp % 10 + '0';
			if(tmp >= 10) flag = true;
			else flag = false;
		}
		if(flag) ret.s[len] = '1';
		return ret;
	}

	void print() {
		int len = strlen(s);
		if(len == 1 && s[0] == '0') {
			printf("0\n");
			return;
		}
		bool flag = true;
		for(int i = len - 1; i >= 0; i--) {
			if(s[i] != '0') flag = false;
			if(flag) continue;
			printf("%c", s[i]);
		}
		printf("\n");
	}
}F[1005], G[1005];

int main() {
	freopen("vans.in", "r", stdin);
	freopen("vans.out", "w", stdout);
	int n;
	scanf("%d", &n);
	F[1] = BigInteger(0);
	F[2] = BigInteger(1);
	F[3] = BigInteger(2);
	G[1] = BigInteger(1);
	G[2] = BigInteger(1);
	G[3] = BigInteger(4);
	for(int i = 4; i <= n; i++) {
		F[i] = F[i - 1] + G[i - 1];
		G[i] = F[i - 1].multi_2() + G[i - 1] + G[i - 2] - G[i - 3];
	}
	F[n].multi_2().print();
	return 0;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值