简单的模拟~~~~~ |
#include
using namespace std;
#define N 50
int n;
int f[N][N];
bool law1(int x,int y){
return (x==1 && y != n) ? true : false;}
bool law2(int x,int y){
return (x!=1 && y == n) ? true : false;}
bool law3(int x,int y){
return (x==1 && y == n) ? true : false;}
bool law4(int x,int y){
return (x!=1 && y != n) ? true : false;}
int main()
{
// freopen("magic.in","r",stdin);
// freopen("magic.out","w",stdout);
scanf("%d",&n);
f[1][n/2+1] = 1;
int x = 1,y = n/2+1;
for(int k=2; k<=n*n; k++){
if(law1(x,y)){
x = n;
y++;
}else
if(law2(x,y)){
x--;
y = 1;
}else
if(law3(x,y)){
x++;
}else
if(law4(x,y)){
if(f[x-1][y+1] == 0){
x--;
y++;
}else x++;
}
f[x][y] = k;
}
for(int i=1; i<=n; i++){
for(int j=1; j<n; j++)
printf("%d ",f[i][j]);
printf("%d\n",f[i][n]);
}
}
一开始感觉有点像并查集啊,但是不知道具体怎么实现。后来发现可以判断最小环,DFS不解释
#include
using namespace std;
#define N 200001
#define Max 0x7f7f7f7f
int n,ans=Max;
int t[N];
bool vis[N];
int pos[N];
void Dfs(int x,int sum,int Start){
if(sum >= ans || sum > n) return;
if(x == Start){
ans = min(ans,sum);
return;
}
if(!vis[x]){
vis[x] = true;pos[x] = sum;
Dfs(t[x],sum+1,Start);
vis[x] = false;pos[x] = 0;
}else{
ans = min(ans,sum - pos[x]);
}
return;
}
int main()
{
// freopen("message.in","r",stdin);
// freopen("message.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&t[i]);
for(int i=1; i<=n; i++)
if(!vis[i]) Dfs(t[i],1,i);
printf("%d",ans);
return 0;
}
AC攻略
#include
using namespace std;
#define N 200001
#define Max 0x7f7f7f7f
int n,ans=Max;
int t[N];
bool vis[N],all_vis[N];
int pos[N];
void Dfs(int x,int sum,int Start){
if(sum >= ans || sum > n || all_vis[x]) return;
if(x == Start){
ans = min(ans,sum);
return;
}
if(!vis[x]){
vis[x] = true;pos[x] = sum;
Dfs(t[x],sum+1,Start);
all_vis[x] = true;
}else{
ans = min(ans,sum - pos[x]);
}
return;
}
int main()
{
// freopen("message.in","r",stdin);
// freopen("message.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&t[i]);
for(int i=1; i<=n; i++)
if(!all_vis[i]) Dfs(t[i],1,i);
printf("%d",ans);
return 0;
}
考场模拟n<=4的情况,结果输入n位置写错,导致零分 。
正解就是先出顺子,再搞散牌!!!
十七张牌,我不信你能秒我?! |
#include
using namespace std;
int dp[25][25][25][25],card[15],h[15];
//dp[i][j][k][l]表示i组四张,j组三张,k组两张,l组单牌所需要的最少步数
int n,t,color,point,ans;
int tnum[5]={0,5,3,2};
int dk(int o,int t2,int t3,int f,int k){//处理KING
if(k==1){
o++;
k=0;
}
if(k==0) return dp[f][t3][t2][o];
else return min(dp[f][t3][t2][o+2],dp[f][t3][t2][o]+1);
}
void dfs(int t){
if(t>ans) return;
memset(h,0,sizeof(h));
for(int i=2;i<=14;i++) h[card[i]]++;
ans=min(ans,t+dk(h[1],h[2],h[3],h[4],card[0]));
for(int k=1;k<=3;k++) //把顺子先处理掉
for(int i=3;i<=14;i++)
{
int j;
for(j=i;j<=14&&card[j]>=k;j++)
{
card[j]-=k;
if(j-i+1>=tnum[k]) dfs(t+1);
}
for(j--;j>=i;j--) card[j]+=k;
}
}
void pre()
{
memset(dp,1,sizeof(dp));
dp[0][0][0][0]=0;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
for(int l=0;l<=n;l++)
if(i*4+j*3+k*2+l<=n)
{
dp[i][j][k][l]=i+j+k+l; //这是最差的情况
if(i){
if(k>=2) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-1][j][k-2][l]+1);// 四带一对
if(l>=2) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-1][j][k][l-2]+1);// 一对单牌
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-1][j][k][l]+1); //都不带
}
if(j){
if(k) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-1][k-1][l]+1); // 3带一对
if(l) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-1][k][l-1]+1); // 3带单
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-1][k][l]+1); // 什么都不带
}
if(k) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j][k-1][l]+1); //对子
if(l) dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j][k][l-1]+1); //单牌
}
}
int main()
{
scanf("%d %d",&t,&n);
pre();
while(t--)
{
memset(card,0,sizeof(card));
ans=n;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&point,&color);
if(point==1) card[14]++;
//因为2不能算顺子,所以将A变为14方便发顺子
else card[point]++;
}
dfs(0);
printf("%d\n",ans);
}
return 0;
}
!!!划重点:最大值最小/最小值最大 => 二分
销魂的码子
#include
using namespace std;
#define LL long long
int n,m;
LL d,a[50001];
bool Judge(LL x){
int last = 0,tot = 0;
for(int i=1; i<=n; i++){
if(a[i]-a[last] < x) tot++;
else last = i;
}
return tot <= m;
}
int main()
{
// freopen("stone.in","r",stdin);
// freopen("stone.out","w",stdout);
scanf("%lld%d%d",&d,&n,&m);
for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
n++;a[n] = d;
LL l = 0,r = a[n],mid;
while(l<=r){
mid = (l+r)/2;
if(Judge(mid))
l = mid+1;
else
r = mid-1;
}
printf("%lld",r);
return 0;
}
看到迪皮就头疼
正解:
#include
using namespace std;
#define mod 1000000007
#define Max 1010
int n,m,k,now;
long long f[2][205][205][2];
char a[Max],b[205];
int main()
{
scanf("%d%d%d\n%s\n%s",&n,&m,&k,a+1,b+1);
int now=1,pre=0;
f[0][0][0][0]=f[1][0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
for(int g=1;g<=k;g++){
if(a[i]==b[j]) f[now][j][g][1] = (f[pre][j-1][g][1] + f[pre][j-1][g-1][1] + f[pre][j-1][g-1][0]) % mod;
else f[now][j][g][1] = 0;
f[now][j][g][0] = (f[pre][j][g][0] + f[pre][j][g][1]) % mod;
}
swap(now,pre);
}
printf("%lld",(f[pre][m][k][0]+f[pre][m][k][1])%mod);
return 0;
}