*【HDU - 4272 】LianLianKan (dfs 或 状压dp,贪心不行)

题干:

I like playing game with my friend, although sometimes looks pretty naive. Today I invent a new game called LianLianKan. The game is about playing on a number stack. 
Now we have a number stack, and we should link and pop the same element pairs from top to bottom. Each time, you can just link the top element with one same-value element. After pop them from stack, all left elements will fall down. Although the game seems to be interesting, it's really naive indeed. 


To prove I am a wisdom among my friend, I add an additional rule to the game: for each top element, it can just link with the same-value element whose distance is less than 6 with it. 
Before the game, I want to check whether I have a solution to pop all elements in the stack. 

Input

There are multiple test cases. 
The first line is an integer N indicating the number of elements in the stack initially. (1 <= N <= 1000) 
The next line contains N integer ai indicating the elements from bottom to top. (0 <= ai <= 2,000,000,000)

Output

For each test case, output “1” if I can pop all elements; otherwise output “0”.

Sample Input

2
1 1
3
1 1 1
2
1000000 1

Sample Output

1
0
0

题目大意:

给你有n个数的栈,连续的6个数中有两个一样的数可以消除,一次只能消除两个,且最头上那个必须被选择(也就是每次必须从头上开始选),问最终这个栈的数能不能被消完。

解题报告:

   刚开始贪心最近的,发现不行,因为可能要消远的  因为可能别人需要用这个来减少距离。后来尝试贪心最远的,,都WA了,看来只能dfs了、、

错误代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1005];
int main()
{int n;while(~scanf("%d",&n)) {vector<ll> vv;for(int i = 1; i<=n; i++) {scanf("%lld",&a[i]);}for(int i = n; i>=1; i--) {vv.push_back(a[i]);}if(n%2 == 1) {printf("0\n");continue;}vector<ll> :: iterator it;int flag = 0;while(1) {it = vv.begin();flag = 0;for(int i = 1; i<=5; i++) {if( ( it+i ) == vv.end()) {flag=0;break;}if(*(it+i) == (*it)) {flag=1;vv.erase(it+i);vv.erase(it);break;}}if(flag == 0) break;if(vv.size() == 0) break;}if(vv.size()) printf("0\n");else printf("1\n");}return 0 ;
}

AC代码:(丑陋的搜索)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
bool vis[MAX];
int flag,n;
void dfs(int cur) {while(cur <= n && vis[cur]) cur++;if(cur > n) {//已经说明vis[n]=1了所以不用判断了 flag = 1;return ;}//if(cur == n) return;//因为已经判断奇偶了,所以这一步也不需要了if(flag) return;vis[cur]=1;int cnt = 0;int j=cur+1;for(; cnt<=5;) {if(j>=n+1) return;if(vis[j]) {j++;continue;}//if(cur+i>n) return;if(a[j] == a[cur]) {vis[j]=1;dfs(cur+1);vis[j]=0;}cnt++;j++;if(flag) return;}vis[cur]=0;
}
map<ll,int>mp;
int main() {while(~scanf("%d",&n)) {flag = 0;mp.clear();for(int i = n; i>=1; i--) {scanf("%lld",&a[i]);vis[i]=0;mp[a[i]]++;}if(n%2 == 1 ) {printf("0\n");continue;}map<ll,int>::iterator it;for(it=mp.begin(); it!=mp.end(); it++) {if((it->second)%2==1) {flag = 2;break;}}if(flag == 2) {puts("0");continue;}dfs(1);if(flag) puts("1");else puts("0");}return 0 ;
}

AC代码3:(把dfs中while那一部分给改了)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
bool vis[MAX];
int flag,n;
void dfs(int cur) {if(cur > n) {flag = 1;return;}if(vis[cur]) {dfs(cur+1);	return;}if(flag) return;vis[cur]=1;int cnt = 0;int j=cur+1;for(; cnt<=5;) {if(j>=n+1) return;if(vis[j]) {j++;continue;}//if(cur+i>n) return;if(a[j] == a[cur]) {vis[j]=1;dfs(cur+1);vis[j]=0;}cnt++;j++;if(flag) return;}vis[cur]=0;
}
map<ll,int>mp;
int main() {while(~scanf("%d",&n)) {flag = 0;mp.clear();for(int i = n; i>=1; i--) {scanf("%lld",&a[i]);vis[i]=0;mp[a[i]]++;}if(n%2 == 1 ) {printf("0\n");continue;}map<ll,int>::iterator it;for(it=mp.begin(); it!=mp.end(); it++) {if((it->second)%2==1) {flag = 2;break;}}if(flag == 2) {puts("0");continue;}dfs(1);if(flag) puts("1");else puts("0");}return 0 ;
}

去掉map:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
bool vis[MAX];
int flag,n;
ll fk;
void dfs(int cur) {if(cur > n) {flag = 1;return;}if(vis[cur]) {dfs(cur+1);return;}if(flag) return;vis[cur]=1;int cnt = 0;int j=cur+1;for(; cnt<=5;) {if(j>=n+1) return;if(vis[j]) {j++;continue;}//if(cur+i>n) return;if(a[j] == a[cur]) {vis[j]=1;dfs(cur+1);vis[j]=0;}cnt++;j++;if(flag) return;}vis[cur]=0;
}
map<ll,int>mp;
int main() {while(~scanf("%d",&n)) {flag = 0;mp.clear();for(int i = n; i>=1; i--) {scanf("%lld",&a[i]);vis[i]=0;fk ^= a[i];}if(n%2 == 1 || fk != 0 ) {printf("0\n");continue;}dfs(1);if(flag) puts("1");else puts("0");}return 0 ;
}

比较美观的版本:(AC代码)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
bool vis[MAX];
int flag,n;
void dfs(int cur) {if(cur > n) {flag = 1; return;}if(vis[cur]) {dfs(cur+1); return;}vis[cur]=1;int cnt = 0;int now=cur+1;for(; cnt<=5;) {if(now>n) return;if(vis[now]) {now++;continue;}if(a[now] == a[cur]) {vis[now]=1;dfs(cur+1);vis[now]=0;}cnt++; now++;if(flag) return;}vis[cur]=0;
}
int main() {while(~scanf("%d",&n)) {flag = 0;for(int i = n; i>=1; i--) {scanf("%lld",&a[i]);vis[i]=0;}if(n%2 == 1 ) {printf("0\n");continue;}dfs(1);if(flag) puts("1");else puts("0");}return 0 ;
}

总结:

  刚开始一直dfs的是TLE或者是WA,,仔细原因就不深究了(太麻烦了),但是代码确实有一个地方写的有问题,首先刚开始dfs是这么实现的。。。

void dfs(int cur) {while(cur <= n && vis[cur]) cur++;if(cur > n && vis[n]) {flag = 1;return ;}if(cur > n) return;if(vis[cur]) {dfs(cur+1);return;}if(flag) return;vis[cur]=1;for(int i = 1; i<=5; i++) {if(vis[cur+i]) continue;if(a[cur+i] == a[cur]) {vis[cur+i]=1;dfs(cur+1);vis[cur+i]=0;}if(flag) return;}vis[cur]=0;
}

这就显然有问题了,,(不保证是原始版本了反正我随便挑了个WA的代码就放上来了),主要就是在于for(int i = 1; i<=5; i++)这里就不对,,因为没有考虑到中间有的数字可能已经被使用过了、题目中说的连续5个数字,,不是真正的物理连续,而是消除之后剩下的数字的连续的五个,所以不能这么写代码、并且还有小错误不断:经常把a[cur]写成a[i]了。。

还有一个地方,主函数中判断每个数出现次数是否是偶数次,经检验,这个剪枝就算不加,也不会TLE。。。

 

方法2:(状压dp)

看了别人的代码发现还有一种神奇的状压dp方法。

首先讨论一点最远能消除的地方,比如点的位置是x,如若想要消除x+1位置处的值,那么至少也得在x-4处开始消除,所以x后面最多能有4个被消除,也就是最多能下落4个位置,能够消除的最远距离是x+9,不会超过10个状态。

我们用dp[i][j]代表到第i个元素,且包含他和后面的十个元素状态为j时,这个是否合法。其中状态j:如果某一位为1,代表已经消除,某一位为0,代表没有消除。

那个t的作用是:判断状态的能否达到的时候要注意判断中间有多少个已经被消除的。

//状压dp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;const int MAXN = 1<<10;
const int bit = 9;int data[MAXN];
bool dp[MAXN][MAXN];int main()
{int i, j, k, N;while(scanf("%d", &N) != EOF){memset(data, -1, sizeof(data));memset(dp, 0, sizeof(dp));for(i=N; i>0; i--){scanf("%d", &data[i]);}dp[0][0] = true;for(i=1; i<=N; i++)for(j=0; j<MAXN; j++){if(dp[i-1][j] == true){///这种状态存在if(j & 1){///本位已经被消除dp[i][j>>1] = true;}else{int t = 0;///纪录已经被消除的,状态1表示被消除,0表示没有for(k=1; k<=bit; k++){if(!(j&(1<<k)) && k-t <=5 &&data[i] == data[i+k]){///可以消除,两者之间的距离应该不超过6dp[i][(j>>1)|(1<<(k-1))] = true;}else if(j & (1<<k))t++;}}}}if(dp[N][0] == true)printf("1\n");elseprintf("0\n");}return 0;
}

再贴两个记忆化dp的博客:链接  和  链接

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中的values函数_巧用valueat函数(快逸免费版)

在制作报表时&#xff0c;经常会遇到将数据库里一列数据按照条件取值后&#xff0c;分为多列显示的需求&#xff0c;例如&#xff1a;数据库中有一列名为type的数据&#xff0c;在报表中&#xff0c;第一列选择type为1的数据&#xff0c;第二列选择type为2的数据。由于受到扩展…

Java设计流程执行器_Java进阶面试精选系列:SpringMVC+SpringBoot+Hibernate+Mybatis+设计模式...

小编精心收集&#xff1a;为金三银四准备&#xff0c;以下面试题先过一遍&#xff0c;为即将到了的面试做好准备&#xff0c;也过一遍基础知识点。一、Spring/Spring MVC1.为什么要使用 spring&#xff1f;2.解释一下什么是 aop&#xff1f;3.解释一下什么是 ioc&#xff1f;3.…

【CCFCSP - 201403-4】无线网络(分层图最短路)

题干&#xff1a; 试题编号&#xff1a;201403-4试题名称&#xff1a;无线网络时间限制&#xff1a;1.0s内存限制&#xff1a;256.0MB问题描述&#xff1a; 问题描述   目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要…

【牛客 - 370E】Rinne Loves Gift(Bellman_Ford判负环,二分,分数规划)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/370/E 来源&#xff1a;牛客网 Rinne 喜欢礼物&#xff0c;也喜欢送礼物 圣诞节快到了&#xff0c;Rinne 要去给给住在城市里的人送礼物 城市的交通可以抽象成一个 n 个点 m 条边的有向图 每条边上有…

【POJ - 2976】【ZOJ - 3068】【SCU - 2992】Dropping tests (01分数规划)

题干&#xff1a; In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be . Given your test scores and a positive integer k, determine how high you can make your cumulative aver…

重写过的url 怎么获取当前页面url java_网站URL重写(Java UrlRewrite 的使用)

现在大部分的网站和商城都会使用到URL重写&#xff0c;接触到这个&#xff0c;也是因为正在做的电子商务商城。URL重写&#xff0c;是将原有的URL采用另一种规则来显示&#xff0c;使得用户方便访问同时也屏蔽一些信息。在此说下它的好处&#xff0c;在开发过程中&#xff0c;经…

【51nod - 1050】循环数组最大子段和(dp)

题干&#xff1a; N个整数组成的循环序列a[1],a[2],a[3],…,a[n]&#xff0c;求该序列如a[i]a[i1]…a[j]的连续的子段和的最大值&#xff08;循环序列是指n个数围成一个圈&#xff0c;因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列&#xff09;。当所给的整数均为负数时和为0。…

Java行业情景分析_Java 设计模式情景分析——单例模式

单例模式可以说是应用最广的模式之一&#xff0c;在应用单例模式时&#xff0c;单例对象的类必须保证只有一个实例存在&#xff0c;而且可以自行实例化并向整个系统提供这个实例。一般在不能自由构造对象的情况下&#xff0c;就会使用单例设计模式&#xff0c;例如创建一个对象…

笔试题 - 汽车加油问题

题干&#xff1a; 第一行输入n&#xff0c;k&#xff0c;代表共有k个加油站&#xff0c;加满油后可以跑n公里。 第二行k1个数&#xff0c;其中前k个数代表加油站的位置&#xff0c;第k1个数代表终点的位置。 一辆车从坐标零点加满油后出发&#xff0c;问最少加几次油&#xff0…

php实现播放直播_PHP直播技术分享(一:实现直播)

推流服务器采用的是自搭的推流服务器 , 自己玩玩 做外包项目还是去搞七牛云/阿里这样的服务器吧,开始bb-----1:技术栈image.jpeg2:开发中业务(1)主播申请时创建个秘钥 , 这个秘钥随时字符串即可到时候根据字符串找到拉流的直播位置存数据库包括推流地址image.png3:配置nginx-rt…

笔试题 - 阶乘问题

题干&#xff1a; 【题意】 给你一个数组n&#xff08;1<n<1e5&#xff09; 让你输出有多少数的阶乘后恰好有n个0&#xff0c;并依次输出。 【类型】 二分or暴力 【分析】 肯定满足&#xff0c;数字越大&#xff0c;其后的0的个数也就越多。 于是我们可以二分出最小的l&…

php获取location,php获取header[‘location’]信息常见问题

15/01/31本文关键字: 302, header, location//初始化url信息$host “#8221;;$url$host.”l/rzTf7ap2viw/&iid222004556&resourceId0_04_05_99/v.swf”;//按照字段获取header响应信息$headers get_headers($url, TRUE);//获取这个土豆的302跳转地址$u302 $headers[“Lo…

【计蒜客 - 蓝桥训练】蒜厂年会(单调队列优化dp,循环数列的最大子段和)

题干&#xff1a; 在蒜厂年会上有一个抽奖&#xff0c;在一个环形的桌子上&#xff0c;有 nn 个纸团&#xff0c;每个纸团上写一个数字&#xff0c;表示你可以获得多少蒜币。但是这个游戏比较坑&#xff0c;里面竟然有负数&#xff0c;表示你要支付多少蒜币。因为这些数字都是…

php对联广告,html左右对联代码 cms网站对联广告html代码

实现网页左右两侧居中的对联广告代码你只记得自己有好多朋友却从没想过小编只有你一人。无标题文档 #left{ width:200px;height:450px; position:absolute; left:0px; background:red; border:1px #000 solid} #right{width:200px;height:450px; position:absolute; right:0px;…

php 分页 url重写 分页问题,解决千古难题,wordpress分页URL问题,wordpress给分页加链接...

原本的wordpress文章如果分页会成如下的结构&#xff1a;http://www.xyqzmt.cn/1.html/2通常固定链接都是这样的结构&#xff0c;设为/%postname%.html或者/%post_id%.html 以前我一直无法解决如上的问题&#xff0c;最后放弃挣扎&#xff0c;如果遇到很长的文章全都放在一个页…

【POJ - 2378】Tree Cutting(树形dp,树的重心变形)

题干&#xff1a; After Farmer John realized that Bessie had installed a "tree-shaped" network among his N (1 < N < 10,000) barns at an incredible cost, he sued Bessie to mitigate his losses. Bessie, feeling vindictive, decided to sabotage…

php 5.5.38 ldap安装,centos5.5系统下面,lnmp环境下面php加载ldap扩展

对于LDAP的安装得先安装检查下面是不是已经安装&#xff0c;如果没有安装之&#xff1a;检查&#xff1a;yum list openldapyum list openldap-devel安装 &#xff1a;yum install openldapyum install openldap-devel一定要执行这条命令&#xff1a;cp -frp /usr/lib64/liblda…

【牛客 - 181F】子序列(容斥,组合数,费马小定理)

题干&#xff1a; 题目描述 给出一个长度为n的序列&#xff0c;你需要计算出所有长度为k的子序列中&#xff0c;除最大最小数之外所有数的乘积相乘的结果 输入描述: 第一行一个整数T&#xff0c;表示数据组数。 对于每组数据&#xff0c;第一行两个整数N&#xff0c;k&#…

php石头剪刀布五局三胜,求程序,下面是剪刀石头布的程序,谁能帮忙改成能选择三局两胜,五局三胜……的?能成功运行的加分...

// 只需要修改main() //#define AllCount 5 // 输入你要选择的赛制&#xff0c;5为五局三胜&#xff0c;3为三局两胜 //#define WinCount AllCount / 2 1 void main() { Play play; int a5; int failure0,win0,tie0; unsigned long begin; int WinCount; int AllCount; printf…

【CodeForces - 1102C 】Doors Breaking and Repairing (思维,简单博弈)

题干&#xff1a; You are policeman and you are playing a game with Slavik. The game is turn-based and each turn consists of two phases. During the first phase you make your move and during the second phase Slavik makes his move. There are nn doors, the i…