poj_3320_Jessica's Reading Problem
hdu_3001_travelling
http://poj.org/problem?id=3320
题意是给你一个序列,要求出一个最短的子序列的长度,子序列要求包括原序列的所有数字。
使用库函数里的map,把出现的第k种数字记为k。然后采用尺取法。l 和 r 记录左右区间,先 r ++,如果 l-1~r 之间符合要求,则记录结果,并且l++;
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 999999999
int a[1000010];
int vis[1000010];
map<int ,int > my_map;
int main(){
int n,cnt=1;
scanf("%d",&n);
for (int i=0;i<n;i++){
scanf ("%d",&a[i]);
if (my_map[a[i]]==0){
my_map[a[i]]=cnt++;
}
}
int count = 1, ans = n;
vis[my_map[a[0]]]=1;
for (int l=0, r=1; ; ){
while ( count<cnt-1 && r<n ) {
if (vis[my_map[a[r]]]==0){
count++;
}
vis[my_map[a[r]]]++;
r++;
}
if (count<cnt-1) break;
if ( count == cnt -1 ) {
ans=min(ans,r-l);
if (vis[my_map[a[l]]] == 1 ) {
count--;
}
vis[my_map[a[l]]]--;
l++;
}
}
printf ("%d\n",ans);
return 0;
}
poj_1159_Palindrome
http://poj.org/problem?id=1159
给出一个长度为 n 的字符串,求出还需要插入几个字符使得字符串成为回文串。先求出最长回文子序列,剩下的就是要插入字符来使得字符串回文的了。另外,内存限制,用%2进行奇偶滚动(ps:n*n的short可以过)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
short dp[5005][2];
int main(int argc, char const *argv[])
{
//freopen ("in.txt","r",stdin);
int n;
char str[5005];
memset(dp,0,sizeof(0));
cin>>n>>str;
dp[0][0]=1;
for (int i = 1; i < n; ++i)
{
dp[i][i%2]=1;
for (int j = i-1; j >= 0; --j)
{
if (str[i]==str[j]){
dp[j][i%2]=dp[j+1][(i-1)%2]+2;
}
else
dp[j][i%2]=max(dp[j+1][i%2],dp[j][(i-1)%2]);
}
}
printf ("%hd\n",n-dp[0][(n-1)%2]);
return 0;
}
hdu_3001_travelling
http://acm.hdu.edu.cn/showproblem.php?pid=3001
前几个礼拜开的这题,连样例都没法过,现在重开,终于各种残疾的过了。
有n个城市,m条道路,可以以任意一个城市作为起点,要求遍历所有的城市,并且每个城市不可以访问超过两次。
以每个城市的访问次数作为状态,就像TSP问题。
如果状态s的第u个城市访问过(两次或者一次),那他可以由状态s-u下的如果第v个城市被访问过+edge[v][s];
这里需要自己构建三进制。把n个城市的状态压缩。至于为什么不用枚举起点而是一次性把起点置为零,还有待脑残,(枚举了后TLE了)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 999999999
int three (int n){
int res=1;
for (int i=0;i<n;i++){
res*=3;
}
return res;
}
int judge (int s,int u){
int res=s;
for (int i=0;i<u-1;i++){
res/=3;
}
return res%3;
}
int dp[59049+3][12];
inline int min (int a,int b){//库的min会TLE ==
if (a<b) return a;
else return b;
}
int main(){//freopen("in.txt","r",stdin);cout<<"*"<<endl;
int n, m;
int map[12][12];
int a,b,c;
while (scanf ("%d%d",&n,&m)==2){
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
map[i][j]=INF;
}
}
for (int i=0;i<m;i++){
scanf ("%d%d%d",&a,&b,&c);
map[a-1][b-1]=map[b-1][a-1]=min(map[a-1][b-1],c);
}
int ans=INF,rec=INF;
{//枚举起点 后来不用了。= =
for (int s=0;s<three(n);s++){
fill (dp[s],dp[s]+n,INF);
}
for (int st=0;st<n;st++){
dp[three(st)][st]=0;
}
rec=INF;
for (int s=0;s<three(n);s++){
for (int k=0;k<n;k++){
if (judge(s,k+1)!=0){
for (int v=0;v<n;v++){
if (judge(s,v+1)!=0){
dp[s][k]=min(dp[s][k],dp[s-three(k)][v]+map[v][k]);
}
}
}
}
int flag=1;
for (int i=1;i<=n;i++){
if(judge(s,i)==0){
flag=0;
}
}
if (flag==1){
for (int j=0;j<n;j++){
rec=min(rec,dp[s][j]);
}
}
}
ans=min(ans,rec);
}
if (ans==INF)printf ("-1\n");
else printf ("%d\n",ans);
}
return 0;
}