USACO 6.1.1 Postal Vans 特例dp
2018-02-10 20:57
267 查看
http://train.usaco.org/usacoprob2?a=iHzQON4VeJX&S=vans
题目大意:由4条横线,N条纵线划划分的网络,要求一条路线经过每个网点一次且仅一次,求共有多少条这样的路径
想法一:枚举,不可能,其实到第五章之后的题目好像都不太能枚举了
想法二:相当于先有一个最外层的大矩形轮廓,然后逐步“下凹”,只要下凹的那一格在当前外表面轮廓组成中只有一条边就不会使最后的结果缺失某个点,而且N确定时下凹的次数是固定的,但是要找到下凹的位置麻烦
想法三:与下凹相反,在网络中选择格子形成一个联通的区域,N确定时格子总数也是确定的,但是要求选择区域在任意位置宽度为一且四角的格子要被包含在这个区域中
正解:基于连通性状态压缩的动态规划
说实话以我现在的能力看不太懂,但这个方法绝对是具有普适性的,所以等以后再好好学习
链接:https://wenku.baidu.com/view/a6dce6c76137ee06eff918d1.html 陈丹琦
特解:因为这道题在横向上只有四条线,所以可以用普通的dp方法处理,真的妙
链接:http://blog.csdn.net/jiangshibiao/article/details/21446033
需要注意的一点就是最后的结果很大,当N = 1000时,结果的位数有400+位,需要自定大数类/*
ID: frontie1
TASK: vans
LANG: C++
*/
#include <iostream>
#include <cstdio>
using namespace std;
struct number
{
int arr[500];
int length;
number()
{
// for(int i = 0; i < 100; ++i){
// arr[i] = 0;
// }
length = 1;
}
number operator+(const number &obj)
{
// this->print();
// cout << " + ";
// obj.print();
// cout << " = ";
number output;
int cur1 = 0, cur2 = 0, cur3 = 0;
int up = 0;
while(cur1 < length && cur2 < obj.length){
output.arr[cur3] = arr[cur1] + obj.arr[cur2] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur1; ++cur2; ++cur3;
}
while(cur1 < length){
output.arr[cur3] = arr[cur1] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur1; ++cur3;
}
while(cur2 < obj.length){
output.arr[cur3] = obj.arr[cur2] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur2; ++cur3;
}
if(up){
output.arr[cur3] = up;
++cur3;
}
output.length = cur3;
// output.print();
// cout << endl;
return output;
}
number operator-(const number &obj)
{
// this->print();
// cout << " - ";
// obj.print();
// cout << " = ";
number output;
int cur1 = 0, cur2 = 0, cur3 = 0;
int down = 0;
while(cur1 < length && cur2 < obj.length){
output.arr[cur3] = arr[cur1] - obj.arr[cur2] - down;
if(output.arr[cur3] < 0){
//cout << output.arr[cur3] << " occurred" << endl;
output.arr[cur3] += 10;
down = 1;
}
else down = 0;
++cur1; ++cur2; ++cur3;
}
while(cur1 < length){
output.arr[cur3] = arr[cur1] - down;
if(output.arr[cur3] < 0){
output.arr[cur3] += 10;
down = 1;
}
else down = 0;
++cur1; ++cur3;
}
while(output.arr[cur3-1] == 0) --cur3;
output.length = cur3;
// output.print();
// cout << endl;
return output;
}
void print() const
{
for(int i = length-1; i >= 0; --i){
cout << arr[i];
}
}
};
int N;
number f[1010];
number g[1010];
//int f[1010];
//int g[1010];
int main()
{
//freopen("vans.in", "r", stdin);
//freopen("vans.out", "w", stdout);
cin >> N;
// f[1] = 0; f[2] = 2;
// g[1] = 2; g[2] = 2;
//
// for(int i = 3; i <= N; ++i){
// f[i] = g[i-1] + f[i-1];
// g[i] = 2*f[i-1] + g[i-1] + g[i-2] - g[i-3];
// cout << f[i] << '\t' << g[i] << endl;
// }
f[1].arr[0] = 0; f[2].arr[0] = 2; f[3].arr[0] = 4;
g[1].arr[0] = 2; g[2].arr[0] = 2; g[3].arr[0] = 8;
for(int i = 4; i <= N; ++i){
f[i] = g[i-1] + f[i-1];
g[i] = ((f[i-1] + f[i-1]) + (g[i-1] + g[i-2])) - g[i-3];
// f[i].print();
// cout << '\t';
// g[i].print();
// cout << endl;
}
f
.print();
cout << endl;
// cout << f
.length << endl;
// for(int i = f
.length-1; i >= 0; --i){
// cout << f
.arr[i];
// }
// cout << endl;
return 0;
}
题目大意:由4条横线,N条纵线划划分的网络,要求一条路线经过每个网点一次且仅一次,求共有多少条这样的路径
想法一:枚举,不可能,其实到第五章之后的题目好像都不太能枚举了
想法二:相当于先有一个最外层的大矩形轮廓,然后逐步“下凹”,只要下凹的那一格在当前外表面轮廓组成中只有一条边就不会使最后的结果缺失某个点,而且N确定时下凹的次数是固定的,但是要找到下凹的位置麻烦
想法三:与下凹相反,在网络中选择格子形成一个联通的区域,N确定时格子总数也是确定的,但是要求选择区域在任意位置宽度为一且四角的格子要被包含在这个区域中
正解:基于连通性状态压缩的动态规划
说实话以我现在的能力看不太懂,但这个方法绝对是具有普适性的,所以等以后再好好学习
链接:https://wenku.baidu.com/view/a6dce6c76137ee06eff918d1.html 陈丹琦
特解:因为这道题在横向上只有四条线,所以可以用普通的dp方法处理,真的妙
链接:http://blog.csdn.net/jiangshibiao/article/details/21446033
需要注意的一点就是最后的结果很大,当N = 1000时,结果的位数有400+位,需要自定大数类/*
ID: frontie1
TASK: vans
LANG: C++
*/
#include <iostream>
#include <cstdio>
using namespace std;
struct number
{
int arr[500];
int length;
number()
{
// for(int i = 0; i < 100; ++i){
// arr[i] = 0;
// }
length = 1;
}
number operator+(const number &obj)
{
// this->print();
// cout << " + ";
// obj.print();
// cout << " = ";
number output;
int cur1 = 0, cur2 = 0, cur3 = 0;
int up = 0;
while(cur1 < length && cur2 < obj.length){
output.arr[cur3] = arr[cur1] + obj.arr[cur2] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur1; ++cur2; ++cur3;
}
while(cur1 < length){
output.arr[cur3] = arr[cur1] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur1; ++cur3;
}
while(cur2 < obj.length){
output.arr[cur3] = obj.arr[cur2] + up;
up = output.arr[cur3] / 10;
output.arr[cur3] %= 10;
++cur2; ++cur3;
}
if(up){
output.arr[cur3] = up;
++cur3;
}
output.length = cur3;
// output.print();
// cout << endl;
return output;
}
number operator-(const number &obj)
{
// this->print();
// cout << " - ";
// obj.print();
// cout << " = ";
number output;
int cur1 = 0, cur2 = 0, cur3 = 0;
int down = 0;
while(cur1 < length && cur2 < obj.length){
output.arr[cur3] = arr[cur1] - obj.arr[cur2] - down;
if(output.arr[cur3] < 0){
//cout << output.arr[cur3] << " occurred" << endl;
output.arr[cur3] += 10;
down = 1;
}
else down = 0;
++cur1; ++cur2; ++cur3;
}
while(cur1 < length){
output.arr[cur3] = arr[cur1] - down;
if(output.arr[cur3] < 0){
output.arr[cur3] += 10;
down = 1;
}
else down = 0;
++cur1; ++cur3;
}
while(output.arr[cur3-1] == 0) --cur3;
output.length = cur3;
// output.print();
// cout << endl;
return output;
}
void print() const
{
for(int i = length-1; i >= 0; --i){
cout << arr[i];
}
}
};
int N;
number f[1010];
number g[1010];
//int f[1010];
//int g[1010];
int main()
{
//freopen("vans.in", "r", stdin);
//freopen("vans.out", "w", stdout);
cin >> N;
// f[1] = 0; f[2] = 2;
// g[1] = 2; g[2] = 2;
//
// for(int i = 3; i <= N; ++i){
// f[i] = g[i-1] + f[i-1];
// g[i] = 2*f[i-1] + g[i-1] + g[i-2] - g[i-3];
// cout << f[i] << '\t' << g[i] << endl;
// }
f[1].arr[0] = 0; f[2].arr[0] = 2; f[3].arr[0] = 4;
g[1].arr[0] = 2; g[2].arr[0] = 2; g[3].arr[0] = 8;
for(int i = 4; i <= N; ++i){
f[i] = g[i-1] + f[i-1];
g[i] = ((f[i-1] + f[i-1]) + (g[i-1] + g[i-2])) - g[i-3];
// f[i].print();
// cout << '\t';
// g[i].print();
// cout << endl;
}
f
.print();
cout << endl;
// cout << f
.length << endl;
// for(int i = f
.length-1; i >= 0; --i){
// cout << f
.arr[i];
// }
// cout << endl;
return 0;
}
相关文章推荐
- USACO6.1.1 Postal Vans (vans) 插头dp
- USACO 6.1 Postal Vans(一道神奇的dp)
- usaco 6.1 Postal Vans(插头DP)
- usaco Postal Vans(dp)
- usaco training 6.1.1 Postal Vans 题解
- USACO Postal Vans 解题报告
- USACO 1.3 Calf Flac (最长回文子串 DP动态规划)
- DP【洛谷P3135】[USACO16JAN]堡哞Fort Moo
- BZOJ 3391 [Usaco2004 Dec]Tree Cutting网络破坏(树形DP)
- [Usaco2008 Mar]土地购买 斜率优化的DP
- 【斜率DP】bzoj1597: [Usaco2008 Mar]土地购买
- [bzoj 1613]: [Usaco2007 Jan]Running贝茜的晨练计划 dp
- 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币 背包dp
- bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 dp
- dp—— [Usaco2007 Jan]Running贝茜的晨练计划
- BZOJ 1606: [Usaco2008 Dec]Hay For Sale 购买干草( dp )
- 【树形dp】Bzoj3391 [Usaco2004 Dec]Tree Cutting网络破坏
- BZOJ 2442: [Usaco2011 Open]修剪草坪( dp )
- [bzoj 1606] [Usaco2008 Dec]Hay For Sale 购买干草 (dp)
- 【BZOJ】1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典(dp)