这个题目上周的对抗赛的,美国2013区域赛的题目,上次比赛真惨,就做出一道题,最多的也只做出两道,当时想把这题做出来,一直TLE。

这个题目用挂在Hunnu OJ的数据可以过,但UVALive上死活过不了,好像UVALive卡的时间不太对,没人过了这道题。

我当初是想用一个dp[s]表示键入状态,然后由dp[0]开始逐渐向上深搜,结果就TLE了,后来比较了一下别人的代码,,果然我这样还是不行

不管我怎么优化,我这一维数组,不能对某个状态马上就返回,因为随时可以再被更新,但是如果用个二维数组,dp[s][i],表示在状态为s的时候,键入第i个字符时候的最小键入数目,就可以只更新一次,下次再遇到这个情况就能马上return了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 18
#define INF 1<<30
using namespace std;
char ch[N];
int len,dp[<<N][N],ALL;
//int up[1<<N][N];
/*
int abs(int a,int b)
{
if (a>b) return a-b;
else return b-a;
}
*/
int diff(int a, int b) //这个函数和下面的函数都是计算转换字符的按键数,结果下面那个是错的,原因是在计算从Z字母转换过去的时候,下面那个算错了,没照顾到a在b的后面的情况。为了这个BUG我检查了好久 真不应该啊
{
int ans=abs(a-b);
return min(ans,'Z'-'A'-ans+);
}
int ccounts(char a,char b)
{
int asc1=a-'A';
int asc2=b-'A';
int z='Z'-'A';
int press=abs(asc1-asc2);
press=min((press),z-asc2++asc1);
return press; }
/*
void solve(int s,int d)
{
if (d==len) return;
//if (vis[s]) return;
vis[s]=1;
if (dp[ALL]<=dp[s]) return;
for (int i=0; i<len; i++)
{
if ((1<<i)&s) continue;
int nt=s+(1<<i);
int tmp;
//cout<<"p1"<<endl;
//if (up[s][i]==0)
//up[s][i]=counts(i,s,ch[i]);
tmp=dp[s]+counts(i,s,ch[i]);
//cout<<"p2"<<endl;
//cout<<tmp<<endl;
if (dp[nt]>tmp)
{
dp[nt]=tmp;
mouse[nt]=i+1;
action[nt]=ch[i]-'A';
solve(nt,d+1);
}
else
if (vis[nt]==0)
solve(nt,d+1);
//cout<<"p3"<<endl;
//cout<<dp[nt]<<endl; }
}
*/
int solve (int s,int last) //记忆化搜索
{
if (dp[s][last]) return dp[s][last];
if (s==) return ;
dp[s][last]=INF;
int pos=;
for (int i=;i<=last;i++)
{
if ((<<i)&s) pos++;
}
for (int i=,j=;i<len;i++)
{
if ((<<i)&s)
{
j++;
if (j==pos) continue;
int cur= j>pos? j-pos:pos-j-;
int rng=diff(ch[i],ch[last]);
dp[s][last]=min(dp[s][last],+cur+rng+solve(s^(<<last),i));
}
}
return dp[s][last]; }
int main()
{
//init();
while (scanf("%s",ch))
{
len=strlen(ch);
if (len== && ch[]=='') break;
memset(dp,,sizeof dp);
ALL=<<len;
ALL--;
for (int i=;i<len;i++)
{
dp[<<i][i]=diff('A',ch[i])+;
}
int ans=INF;
for (int i=;i<len;i++){
ans=min(ans,solve(ALL,i));
}
printf("%d\n",ans);
}
return ;
}

UVALive 6491 You win! 状态DP的更多相关文章

  1. hdu 4614 pieces 状态DP

    题意:给你一个长度小于等于16的字符串,每次可以删除一个回文传,问你最少删除干净的字数. 状态+dp dp[i] = min(dp[i],dp[j]+dp[j^i]);(j是i的字串): 连接:htt ...

  2. hdu 4778 Gems Fight! 博弈+状态dp+搜索

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...

  3. POJ 3254 压缩状态DP

    题意:一个矩形网格,可以填0或1, 但有些位置什么数都不能填,要求相邻两个不同时为1,有多少种填法.矩形大小最大 12*12. 压缩状态DP大多有一个可行的state的范围,先求出这个state范围, ...

  4. 【状态DP】 HDU 1074 Doing Homework

    原题直通车:HDU  1074  Doing Homework 题意:有n门功课需要完成,每一门功课都有时间期限t.完成需要的时间d,如果完成的时间走出时间限制,就会被减 (d-t)个学分.问:按怎样 ...

  5. Hdu 4539 【状态DP】.cpp

    题意: 一个炮兵可以攻打和他之间曼哈顿距离为2的士兵,给出你一块n*m的战场,告诉你哪些地方可以站人哪些地方不可以,问你最多可以安放多少个士兵? n <= 100, m <= 10 思路: ...

  6. hihocoder第42周 3*N骨牌覆盖(状态dp+矩阵快速幂)

    http://hihocoder.com/contest/hiho42/problem/1 给定一个n,问我们3*n的矩阵有多少种覆盖的方法 第41周做的骨牌覆盖是2*n的,状态转移方程是dp[i] ...

  7. hdu 5135(2014广州—状态dp)

    t题意:给你n条边,构造任意个三角形,一个三角形恰好只用3条边,每条边只能一次,求面积最大值 思路: 最开始想的是先排序从大到小取,但感觉并不怎么靠谱. 最多12条边,所以可以求出所有可能的三角形面积 ...

  8. Hdu 3001 Travelling 状态DP

    题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...

  9. lightoj 1244 - Tiles 状态DP

    思路:状态DP dp[i]=2*dp[i-1]+dp[i-3] 代码如下: 求出循环节部分 1 #include<stdio.h> 2 #define m 10007 3 int p[m] ...

随机推荐

  1. 016.Oracle数据库,取本季度第一天,取本季度最后一天

    /*取本季度第一天,取本季度最后一天*/ SELECT trunc(sysdate, 'Q') AS 本季度第一天 , add_months(trunc(sysdate, ) AS 本季度最后一天 F ...

  2. git参考

    https://github.com/NewLifeX  (redis.mq.数据海量查询.分布式任务调度)

  3. LeetCode实战练习题目 - Array

    实战练习题目 - Array 盛最多水的容器 class Solution { public: int maxArea(vector<int>& height) { int res ...

  4. POJ 3393:Lucky and Good Months by Gregorian Calendar 年+星期 模拟

    Lucky and Good Months by Gregorian Calendar Time Limit: 1000MS   Memory Limit: 65536K Total Submissi ...

  5. CentOS 6.x 重置root 密码

    1.重启,进入启动界面,快速按e,进入GNU GRUB界面. 2.选择第二项,按e,进行编辑. 3.在末尾输入1或single,回车,返回上一界面,还是选第二项,按b,进入单用户模式. 此时输入命令  ...

  6. JWT跨域身份验证解决方案

    JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.本文介绍JWT的原理和用法. 1. 当前跨域身份验证的问题 Internet服务无法与用户身份验证分开.一般过程如下.1.用户 ...

  7. centos下安装tomcat8.

    一.tomcat安装之前,首先安装java jdk,所以手首先将相关安装包都下载传到虚拟机上 1.下载java的linux----jdk1.8安装 到官网上下载与本虚拟机版本位相适应的位节数的Linu ...

  8. oracle查询SQL优化相当重要

    如果表中的时间字段是索引,那么时间字段不要使用函数,函数会使索引失效. 例如: select * from mytable where trunc(createtime)=trunc(sysdate) ...

  9. Spark调优(一)

    一.对多次使用的RDD进行持久化 如何选择一种最合适的持久化策略? 默认情况下,性能最高的当然是MEMORY_ONLY,但前提是你的内存必须足够足够大, 可以绰绰有余地存放下整个RDD的所有数据.因为 ...

  10. CF1141E Superhero Battle

    A superhero fights with a monster. The battle consists of rounds, each of which lasts exactly n minu ...