POJ - 1463 Strategic game (树状动态规划)
这题做的心塞。。。
整个思路非常清晰,d[i][0]表示第i个结点不设置监察的情况下至少需要的数量;d[i][1]表示第i个结点设置检查的情况下的最小需要的数量。
状态转移方程见代码。
但是万万没想到的是,在实现过程中修改了4遍代码,wa了若干次才AC。。。。
下面来总结一下各种wa代码:
版本1:开二维数组存储树(本质上是邻接矩阵存储,把树存储成图),报错TLE。这时候第一感觉是每次更新d[i]的时候都需要遍历一遍邻接表中的所有结点不管是否是子节点都需要遍历。也就是完整的n*n复杂度。因此有了第一次修改,考虑存储的时候用vector只存储子节点从而减少遍历时的数量。(见版本2)
上代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<algorithm>
using namespace std;
//TLE 应该是在更新d[i][]的时候每次都需要遍历n个数,复杂度为o(n^2)
const int maxn=;
int d[maxn][];
int gra[maxn][maxn];
int flag[maxn];
int n;
void dp(int cur){
flag[cur]=;
if(d[cur][]>=||d[cur][]>=){
return;
}
int leaf=;
for(int i=;i<n;i++){
if(gra[cur][i]&&flag[i]!=){
leaf=;
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
if(leaf==){
d[cur][]=;d[cur][]=;
}
}
int main(void){
while(scanf("%d",&n)){
memset(flag,,sizeof(flag));
memset(gra,,sizeof(gra));
memset(d,-,sizeof(d));
int x,cnt;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
while(cnt--){
int tem;
scanf("%d",&tem);
gra[x][tem]=;
gra[tem][x]=;
}
}
dp(x);
int ans=min(d[x][],d[x][]);
cout<<ans<<endl;
}
return ;
}
版本2代码:拟通过vector减少遍历的结点个数(只遍历子节点)。这次修改后果然没有报TLE,但是报了另外一个错:MLE。。。
所以说使用stl还是要慎重。。这时再看了一遍输入样例,发现其实这个输入是按标准的有向树输入的;换句话说根本不需要构造图来解,只需要每个结点记录其父亲即可。
这样一算,存储的数据量瞬间减半。因此有了版本3代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<vector>
using namespace std;
//memory limit
const int maxn=;
int d[maxn][];
//int gra[maxn][maxn];
vector<int>gra[maxn];
bool flag[maxn];
int n;
void dp(int cur){
flag[cur]=;
if(d[cur][]>=||d[cur][]>=){
return;
}
else{
int leaf=;
for(int i=;i<gra[cur].size();i++){
int next=gra[cur][i];
if(flag[next]==){
leaf=;
dp(next);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[next][];
d[cur][]+=min(d[next][],d[next][]);
}
}
d[cur][]++;
if(leaf==){
d[cur][]=;d[cur][]=;
}
}
}
int main(void){
while(scanf("%d",&n)!=EOF){
memset(flag,,sizeof(flag));
memset(gra,,sizeof(gra));
memset(d,-,sizeof(d));
int x,cnt;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
while(cnt--){
int tem;
scanf("%d",&tem);
gra[x].push_back(tem);
gra[tem].push_back(x);
}
}
dp(x);
int ans=min(d[x][],d[x][]);
cout<<ans<<endl;
}
return ;
}
版本3代码:本来以为这个可以直接AC的,结果又一次TLE。。。而且这次的错误找了好久没想到。
最后发现出现在了scanf上。。。
版本3中的代码while(scanf("%d",&n)) 改成while(scanf("%d",&n)!=EOF)或者while(~scanf("%d",&n))就AC了(真的是,秀了一波骚操作。侧面反映基础不太扎实。。。。)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int d[maxn][];
int pre[maxn];
int childcnt[maxn];
int n;
void dp(int cur){
if(d[cur][]>=||d[cur][]>=){
return;
}
if(childcnt[cur]==){
d[cur][]=;d[cur][]=;
return ;
}
for(int i=;i<n;i++){
if(pre[i]==cur){
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
}
int main(void){
while(scanf("%d",&n)){
memset(pre,-,sizeof(pre));
memset(d,-,sizeof(d));
int x,cnt,root=-;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
childcnt[x]=cnt;
if(root==-)root=x;
while(cnt--){
int tem;
scanf("%d",&tem);
pre[tem]=x;
if(tem==root){
root=x;
}
}
}
dp(root);
int ans=min(d[root][],d[root][]);
printf("%d\n",ans);
}
return ;
}
AC代码如下:哎,任重而道远,,,太菜了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int d[maxn][];
int pre[maxn];
int childcnt[maxn];
int n;
void dp(int cur){
if(d[cur][]>=||d[cur][]>=){
return;
}
if(childcnt[cur]==){
d[cur][]=;d[cur][]=;
return ;
}
for(int i=;i<n;i++){
if(pre[i]==cur){
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
}
int main(void){
while(scanf("%d",&n)!=EOF){//万万没想到是这里出错
memset(pre,-,sizeof(pre));
memset(d,-,sizeof(d));
int x,cnt,root=-;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
childcnt[x]=cnt;
if(root==-)root=x;
while(cnt--){
int tem;
scanf("%d",&tem);
pre[tem]=x;
if(tem==root){
root=x;
}
}
}
dp(root);
int ans=min(d[root][],d[root][]);
printf("%d\n",ans);
}
return ;
}
POJ - 1463 Strategic game (树状动态规划)的更多相关文章
- POJ 2352 Stars(树状数组)
Stars Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30496 Accepted: 13316 Descripti ...
- POJ 3321 Apple Tree (树状数组+dfs序)
题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...
- poj 2828 Buy Tickets(树状数组 | 线段树)
题目链接:poj 2828 Buy Tickets 题目大意:给定N,表示有个人,给定每一个人站入的位置,以及这个人的权值,如今按队列的顺序输出每一个人的权值. 解题思路:第K大元素,非常巧妙,将人入 ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数)
链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...
- poj 3067 Japan(树状数组求逆序数)
链接:http://poj.org/problem?id=3067 题意:左边有n个城市,右边有m个城市,建k条道路,问有这k条道路中有多少个交点. 分析:将城市按x和y从小到大排序,对于每条道路,求 ...
- POJ 2299 Ultra-QuickSort(树状数组+离散化)
http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,9 ...
- POJ 3067 Japan 【树状数组经典】
题目链接:POJ 3067 Japan Japan Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32076 Accep ...
- POJ 2155 Matrix(树状数组+容斥原理)
[题目链接] http://poj.org/problem?id=2155 [题目大意] 要求维护两个操作,矩阵翻转和单点查询 [题解] 树状数组可以处理前缀和问题,前缀之间进行容斥即可得到答案. [ ...
随机推荐
- JavaWeb温习之Cookie对象
1. 会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话.有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾 ...
- 以前做的H5推广小游戏(活动及派发奖品形式)
润百颜 1 微信授权登录,获取用户openid.一个openid一次抽奖机会,该openid用户多次玩游戏抽奖,仍然是相同的优惠码. 2 游戏结束抽奖,100%中奖,获得优惠码.优惠码和openid保 ...
- mac必备软件
LigthPaper:Markdown工具 ssh工具:ShellCraft
- 04.ActiveMQ与Spring JMS整合
SpringJMS使用参考:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html ...
- jQuery 的attr()方法
在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^ jque ...
- 转!!CMPP 网关错误码说明
http://www.163duanxin.com/msg/1753.htm CMPP错误码说明 与中国移动代码的对应关系. MI::zzzzSMSC返回状态报告的状态值为EXPIREDMJ:zz ...
- C++ Design Pattern: What is a Design Pattern?
Q: What is a Design Pattern? A: Design Patterns represent solutions to problems what arise when deve ...
- 【spring mvc】扒一扒tomcat
1.TOMCAT的目录 主要说一下webapps目录,WEB应用的目录结构:假设在$CATALINA_HOME/webapps下有helloapp的web应用 /helloapp:Web应用的根目录, ...
- /etc/rc.d/rc.local linux启动自动开启某些服务(转)
/etc/rc.d/rc.local似乎是很多Linux系统管理员的偏爱,因为凡是需要随系统自动启动的服务.程序等,只要系统没有提供Sys V风格的启动脚本,就把这些需求都塞到/etc/rc.d/rc ...
- 数据挖掘-逻辑Logistic回归
逻辑回归的基本过程:a建立回归或者分类模型--->b 建立代价函数 ---> c 优化方法迭代求出最优的模型参数 --->d 验证求解模型的好坏. 1.逻辑回归模型: 逻辑回归(L ...